WPF Listbox layout: multiple columns - c#

I have a ListBox (WPF) that contains CheckBoxes. I'm using is in a configuration screen. Schematic example below:
Now I want to add a "Test 5" CheckBox. I have limited vertical space, so I want it to appear in the horizontal direction, as shown below:
Can the ListBox layout be modified so the CheckBoxes will be arranged like this?

<ListBox Name="CategoryListBox"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=RefValues,
UpdateSourceTrigger=PropertyChanged}"
SelectionMode="Multiple">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal"
MinWidth="150" MaxWidth="150"
Margin="0,5, 0, 5" >
<CheckBox
Name="checkedListBoxItem"
IsChecked="{Binding
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListBoxItem} },
Path=IsSelected, Mode=TwoWay}" />
<ContentPresenter
Content="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=Content}"
Margin="5,0, 0, 0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
or as simple as this:
<Grid>
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem>listbox item 1</ListBoxItem>
<ListBoxItem>listbox item 2</ListBoxItem>
<ListBoxItem>listbox item 3</ListBoxItem>
<ListBoxItem>listbox item 4</ListBoxItem>
<ListBoxItem>listbox item 5</ListBoxItem>
</ListBox>
</Grid>

I encountered a similar problem and eibhrum's answer gave me some idea. I used the following code and I think this also what you need. I used UniformGrid instead of WrapPanel.
<ListBox HorizontalAlignment="Stretch"
ItemsSource="{Binding Timers}"
>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<!-- UNIFORM GRID HERE -->
<UniformGrid Columns="3" IsItemsHost="True"
HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Vertical" >
<TextBlock Text="{Binding Label}" TextWrapping="Wrap"/>
<Separator Margin="5,0,10,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

I know this is an older post, but I stumbled across a fairly simple way to do this while I was trying to solve the same problem here: http://social.technet.microsoft.com/wiki/contents/articles/19395.multiple-columns-in-wpf-listbox.aspx
Just add your binding data source (or add items as needed).
<ListBox Name="myLB" ScrollViewer.HorizontalScrollBarVisiblity="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>

ListBox with multi column and ListBoxItem Orientation is Vertical.
ListBox has fix Height and Auto Width. When add ListBoxItem, ListBox will Auto increase Width.
<ListBox Height="81" VerticalAlignment="Top" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem Content="1"/>
<ListBoxItem Content="2"/>
<ListBoxItem Content="3"/>
<ListBoxItem Content="4"/>
<ListBoxItem Content="5"/>
<ListBoxItem Content="6"/>
<ListBoxItem Content="7"/>
<ListBoxItem Content="8"/>
<ListBoxItem Content="9"/>
<ListBoxItem Content="10"/>
</ListBox>
ListBox with multi column and ListBoxItem Orientation is Horizontal. ListBox has fix Width and Auto Height. When add ListBoxItem, ListBox will Auto increase Height.
<ListBox Width="81" VerticalAlignment="Top" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem Content="1"/>
<ListBoxItem Content="2"/>
<ListBoxItem Content="3"/>
<ListBoxItem Content="4"/>
<ListBoxItem Content="5"/>
<ListBoxItem Content="6"/>
<ListBoxItem Content="7"/>
<ListBoxItem Content="8"/>
<ListBoxItem Content="9"/>
<ListBoxItem Content="10"/>
</ListBox>

If you need to flow rows between multiple regions (multiple windows, in my case), you can use a custom panel implementation.
Example usage:
<Grid>
<Grid.Resources>
<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
<local:SharedLayoutStackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
<local:SharedLayoutCoordinator x:Key="slc" ItemsSource="{Binding Path=MyItems}" />
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Margin="10,10,5,10" BorderBrush="Black" BorderThickness="1">
<ListBox
local:SharedLayoutCoordinator.Region="{Binding Source={StaticResource slc}, Path=[0]}"
ItemsPanel="{StaticResource ResourceKey=ItemsPanelTemplate}" />
</Border>
<Border Grid.Column="1" Margin="5,10" BorderBrush="Black" BorderThickness="1">
<ListBox
local:SharedLayoutCoordinator.Region="{Binding Source={StaticResource slc}, Path=[1]}"
ItemsPanel="{StaticResource ResourceKey=ItemsPanelTemplate}" />
</Border>
<Border Grid.Column="2" Margin="5,10,10,10" BorderBrush="Black" BorderThickness="1">
<ListBox
local:SharedLayoutCoordinator.Region="{Binding Source={StaticResource slc}, Path=[2]}"
ItemsPanel="{StaticResource ResourceKey=ItemsPanelTemplate}" />
</Border>
</Grid>
Results in:
Full demo implementation is available on Github, but the key bits are below.
SharedLayoutCoordinator.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace MultiRegionListBox
{
internal class SharedLayoutCoordinator : DependencyObject
{
private List<SharedLayoutRegion> Regions = new List<SharedLayoutRegion>();
public SharedLayoutRegion this[int index]
{
get
{
var slr = new SharedLayoutRegion(this, index);
for (int i = 0; i < Regions.Count; i++)
{
if (Regions[i].Index > index)
{
Regions.Insert(i, slr);
return slr;
}
}
Regions.Add(slr);
return slr;
}
}
public object ItemsSource
{
get { return (object)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(object), typeof(SharedLayoutCoordinator), new PropertyMetadata(null));
public static SharedLayoutRegion GetRegion(DependencyObject obj)
{
return (SharedLayoutRegion)obj.GetValue(RegionProperty);
}
public static void SetRegion(DependencyObject obj, SharedLayoutRegion value)
{
obj.SetValue(RegionProperty, value);
}
public static readonly DependencyProperty RegionProperty =
DependencyProperty.RegisterAttached("Region", typeof(SharedLayoutRegion),
typeof(SharedLayoutCoordinator), new PropertyMetadata(null, Region_Changed));
private static void Region_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var itemsControl = (ItemsControl)d;
var newController = (SharedLayoutRegion)e.NewValue;
if (newController == null)
{
return;
}
itemsControl.SetBinding(ItemsControl.ItemsSourceProperty, new Binding(nameof(ItemsSource)) { Source = newController.Coordinator });
}
public static SharedLayoutRegion GetParentSharedLayoutController(DependencyObject obj)
{
while (obj != null)
{
if (obj is ItemsControl ic)
{
var slc = GetRegion(ic);
if (slc != null)
{
return slc;
}
}
obj = VisualTreeHelper.GetParent(obj);
}
return null;
}
public IEnumerable<SharedLayoutRegion> GetPreceedingRegions(SharedLayoutRegion region)
{
return Regions.Where(r => r.Index < region.Index);
}
internal SharedLayoutRegion GetNextRegion(SharedLayoutRegion region)
{
var idx = Regions.IndexOf(region);
if (idx + 1 < Regions.Count)
{
return Regions[idx + 1];
}
return null;
}
internal SharedLayoutRegion GetPreviousRegion(SharedLayoutRegion region)
{
var idx = Regions.IndexOf(region);
if (idx > 0)
{
return Regions[idx - 1];
}
return null;
}
}
internal class SharedLayoutRegion
{
private Action InvalidateMeasureCallback;
public SharedLayoutRegion(SharedLayoutCoordinator coord, int index)
{
this.Coordinator = coord;
this.Index = index;
}
public SharedLayoutCoordinator Coordinator { get; }
public int Index { get; }
public SharedLayoutStackPanel Panel { get; set; }
public bool IsMeasureValid
=> !(Panel == null || !Panel.IsMeasureValid || Panel.IsMeasureMeaningless);
internal bool CanMeasure(Action invalidateMeasure)
{
if (Coordinator.GetPreceedingRegions(this).All(pr => pr.IsMeasureValid))
{
return true;
}
this.InvalidateMeasureCallback = invalidateMeasure;
return false;
}
public int StartOfRegion => Coordinator.GetPreviousRegion(this)?.EndOfRegion ?? 0;
public int CountInRegion { get; set; }
public int EndOfRegion => CountInRegion + StartOfRegion;
public bool HasNextRegion => Coordinator.GetNextRegion(this) != null;
internal void OnMeasure()
{
var nextRegion = Coordinator.GetNextRegion(this);
if (nextRegion != null && nextRegion.InvalidateMeasureCallback != null)
{
nextRegion.InvalidateMeasureCallback();
nextRegion.InvalidateMeasureCallback = null;
}
}
}
}
SharedLayoutStackPanel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace MultiRegionListBox
{
class SharedLayoutStackPanel : Panel, IScrollInfo
{
internal const double _scrollLineDelta = 16.0;
public void LineUp() => SetVerticalOffset(VerticalOffset - _scrollLineDelta);
public void LineDown() => SetVerticalOffset(VerticalOffset + _scrollLineDelta);
public void LineLeft() => SetHorizontalOffset(HorizontalOffset - 1.0);
public void LineRight() => SetHorizontalOffset(HorizontalOffset + 1.0);
public void PageUp() => SetVerticalOffset(VerticalOffset - ViewportHeight);
public void PageDown() => SetVerticalOffset(VerticalOffset + ViewportHeight);
public void PageLeft() => SetHorizontalOffset(HorizontalOffset - ViewportWidth);
public void PageRight() => SetHorizontalOffset(HorizontalOffset + ViewportWidth);
public void MouseWheelUp() => SetVerticalOffset(VerticalOffset - SystemParameters.WheelScrollLines * _scrollLineDelta);
public void MouseWheelDown() => SetVerticalOffset(VerticalOffset + SystemParameters.WheelScrollLines * _scrollLineDelta);
public void MouseWheelLeft() => SetHorizontalOffset(HorizontalOffset - 3.0 * _scrollLineDelta);
public void MouseWheelRight() => SetHorizontalOffset(HorizontalOffset + 3.0 * _scrollLineDelta);
public double ExtentWidth => Extent.Width;
public double ExtentHeight => Extent.Height;
public double ViewportWidth => Viewport.Width;
public double ViewportHeight => Viewport.Height;
public double HorizontalOffset => ComputedOffset.X;
public double VerticalOffset => ComputedOffset.Y;
public void SetHorizontalOffset(double offset)
{
if (double.IsNaN(offset))
{
throw new ArgumentOutOfRangeException();
}
if (offset < 0d)
{
offset = 0d;
}
if (offset != Offset.X)
{
Offset.X = offset;
InvalidateMeasure();
}
}
/// <summary>
/// Set the VerticalOffset to the passed value.
/// </summary>
public void SetVerticalOffset(double offset)
{
if (double.IsNaN(offset))
{
throw new ArgumentOutOfRangeException();
}
if (offset < 0d)
{
offset = 0d;
}
if (offset != Offset.Y)
{
Offset.Y = offset;
InvalidateMeasure();
}
}
public ScrollViewer ScrollOwner
{
get { return _scrollOwner; }
set
{
if (value == _scrollOwner)
{
return;
}
InvalidateMeasure();
Offset = new Vector();
Viewport = Extent = new Size();
_scrollOwner = value;
}
}
public bool CanVerticallyScroll
{
get { return true; }
set { /* noop */ }
}
public bool CanHorizontallyScroll
{
get { return false; }
set { /* noop */ }
}
internal bool IsMeasureMeaningless { get; private set; }
protected override void OnVisualParentChanged(DependencyObject oldParent)
{
base.OnVisualParentChanged(oldParent);
this.SLC = SharedLayoutCoordinator.GetParentSharedLayoutController(this);
if (SLC != null)
{
this.SLC.Panel = this;
}
InvalidateMeasure();
}
protected override Size MeasureOverride(Size viewportSize)
{
if (SLC == null || !SLC.CanMeasure(InvalidateMeasure))
{
IsMeasureMeaningless = true;
return viewportSize;
}
IsMeasureMeaningless = false;
var extent = new Size();
var countInRegion = 0; var hasNextRegion = SLC.HasNextRegion;
foreach (var child in InternalChildren.Cast<UIElement>().Skip(SLC.StartOfRegion))
{
child.Measure(new Size(viewportSize.Width, double.PositiveInfinity));
var childDesiredSize = child.DesiredSize;
if (hasNextRegion && extent.Height + childDesiredSize.Height > viewportSize.Height)
{
break;
}
extent.Width = Math.Max(extent.Width, childDesiredSize.Width);
extent.Height += childDesiredSize.Height;
SLC.CountInRegion = countInRegion += 1;
}
// Update ISI
this.Extent = extent;
this.Viewport = viewportSize;
this.ComputedOffset.Y = Bound(Offset.Y, 0, extent.Height - viewportSize.Height);
this.OnScrollChange();
SLC.OnMeasure();
return new Size(
Math.Min(extent.Width, viewportSize.Width),
Math.Min(extent.Height, viewportSize.Height));
}
private static double Bound(double c, double min, double max)
=> Math.Min(Math.Max(c, Math.Min(min, max)), Math.Max(min, max));
protected override Size ArrangeOverride(Size arrangeSize)
{
if (IsMeasureMeaningless)
{
return arrangeSize;
}
double cy = -ComputedOffset.Y;
int i = 0, i_start = SLC.StartOfRegion, i_end = SLC.EndOfRegion;
foreach (UIElement child in InternalChildren)
{
if (i >= i_start && i < i_end)
{
child.Arrange(new Rect(0, cy, Math.Max(child.DesiredSize.Width, arrangeSize.Width), child.DesiredSize.Height));
cy += child.DesiredSize.Height;
}
else if (child.RenderSize != new Size())
{
child.Arrange(new Rect());
}
i += 1;
}
return arrangeSize;
}
private void OnScrollChange() => ScrollOwner?.InvalidateScrollInfo();
public Rect MakeVisible(Visual visual, Rect rectangle)
{
// no-op
return rectangle;
}
internal ScrollViewer _scrollOwner;
internal Vector Offset;
private Size Viewport;
private Size Extent;
private Vector ComputedOffset;
private SharedLayoutRegion SLC;
}
}

My Solution : Using a WrapPanel with a vertical Orientation. Work fine if you adjust the height of the WrapPanel to the Height of the ListBox.
<ListBox ItemsSource="{Binding mySource}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualHeight}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem IsChecked="{Binding checked}">
<CheckBox IsChecked="{Binding checked}" Content="{Binding Name}" />
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Related

Using Update button in WPF ListView to update Selected Item

I have to make a WPF App to add, delete and update Items for Client Management purposes. I have so far been able to add and remove the items to the List using MVVM but I am unable to update the selected items. I require help in this regard.
The code for the project is as follows:
Details Class.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_2.Model
{
public class Details :INotifyPropertyChanged
{
private string name;
public string Name
{ get { return name; } set { name = value; OnPropertyChanged(Name); } }
private string company;
public string Company
{ get { return company; } set { company = value; OnPropertyChanged(Company); } }
private string region;
public string Region
{ get { return region; } set { region = value; OnPropertyChanged(Region); } }
private string hra;
public string HRA
{
get { return hra; }
set
{
hra = value;
OnPropertyChanged(HRA);
}
}
private string basic;
public string Basic
{ get { return basic; }
set { basic = value;
OnPropertyChanged(Basic);
}
}
private string pf;
public string PF
{ get { return pf; }
set
{
pf = value;
OnPropertyChanged(PF);
}
}
private string salary;
public string Salary
{ get { return salary; }
set
{
salary = value;
OnPropertyChanged(Salary);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string det)
{
PropertyChangedEventHandler pc = PropertyChanged;
if (pc != null)
pc(this, new PropertyChangedEventArgs(det));
}
}
}
DetailsViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Assignment_2.Commands;
using Assignment_2.Model;
namespace Assignment_2.ViewModel
{
public class DetailsViewModel : INotifyPropertyChanged
{
private Details record;
public Details Record
{
get { return record; }
set { record = value; NotifyPropertyChanged("Record"); }
}
private ObservableCollection<Details> records;
public ObservableCollection<Details> Records
{
get { return records; }
set { records = value; } // NotifyPropertyChanged("Records");
}
private ICommand _SubmitCommand;
public ICommand SubmitCommand
{
get
{
if (_SubmitCommand == null)
{
_SubmitCommand = new RelayCommand(SubmitExecute, CanSubmitExecute, false);
}
return _SubmitCommand;
}
}
public DetailsViewModel()
{
Record = new Details();
Records = new ObservableCollection<Details>();
}
private void SubmitExecute(object parameter)
{
var TempRecord = new Details();
//TempRecord = Record;
TempRecord.Name = Record.Name;
TempRecord.Company = Record.Company;
TempRecord.Region = Record.Region;
TempRecord.HRA = Record.HRA;
TempRecord.Salary = Record.Salary;
TempRecord.Basic = Record.Basic;
TempRecord.PF = Record.PF;
Records.Add(TempRecord);
}
private bool CanSubmitExecute(object parameter)
{
if (string.IsNullOrEmpty(Record.Name) || string.IsNullOrEmpty(Record.Company))
{
return false;
}
else
{
return true;
}
}
private ICommand _SubmitCommand1;
public ICommand SubmitCommand1
{
get
{
if (_SubmitCommand1 == null)
{
_SubmitCommand1 = new RelayCommand(SubmitExecute1, CanSubmitExecute1, false);
}
return _SubmitCommand1;
}
}
public int findIndex(Details myDetails)
{
int count = 0;
for (int i = 0; i < Records.Count; i++)
{
count = 0;
Details myRecord = Records[i];
if (myRecord.Name == myDetails.Name)
count++;
else continue;
if (myRecord.Company == myDetails.Company)
count++;
else continue;
if (myRecord.Region == myDetails.Region)
count++;
else continue;
if (myRecord.Salary == myDetails.Salary)
count++;
else continue;
if (myRecord.HRA == myDetails.HRA)
count++;
else continue;
if (myRecord.Basic == myDetails.Basic)
count++;
else continue;
if (myRecord.PF == myDetails.PF)
count++;
else continue;
if (count == 7)
return i;
}
return -1;
}
private void SubmitExecute1(object parameter)
{
Records.Remove((Details)parameter);
}
private bool CanSubmitExecute1(object parameter)
{
if (string.IsNullOrEmpty(Record.Name) || string.IsNullOrEmpty(Record.Company))
{
return false;
}
else
{
return true;
}
}
private ICommand _SubmitCommand2;
public ICommand SubmitCommand2
{
get
{
if (_SubmitCommand2 == null)
{
_SubmitCommand2 = new RelayCommand(SubmitExecute2, CanSubmitExecute2, false);
}
return _SubmitCommand2;
}
}
private void SubmitExecute2(object parameter)
{
}
private bool CanSubmitExecute2(object parameter)
{
if (string.IsNullOrEmpty(Record.Name) || string.IsNullOrEmpty(Record.Company))
{
return false;
}
else
{
return true;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string de)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(de));
}
}
}
RelayCommand.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Assignment_2.Commands
{
class RelayCommand : ICommand
{
Action<object> executeAction;
Func<object, bool> canExecute;
bool canExecuteCache;
public RelayCommand(Action<object> executeAction, Func<object, bool> canExecute, bool canExecuteCache)
{
this.canExecute = canExecute;
this.executeAction = executeAction;
canExecuteCache = canExecuteCache;
}
public bool CanExecute(object parameter)
{
if (canExecute == null)
{
return true;
}
else
{
return canExecute(parameter);
}
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public void Execute(object parameter)
{
executeAction(parameter);
}
}
}
MainWindow.xaml
<Window x:Class="Assignment_2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:Assignment_2.ViewModel"
Title="MainWindow" Height="401" Width="472">
<Window.Resources>
<vm:DetailsViewModel x:Key="DetailsViewModel"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource DetailsViewModel}}" RenderTransformOrigin="0.5,0.5" Margin="0,0,1,1">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-0.21"/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="20.59"/>
<RowDefinition Height="22.906"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="29*"/>
<RowDefinition Height="293*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Text=" Name" HorizontalAlignment="Center" Margin="0,0,0,4" Grid.RowSpan="2" Width="35" />
<TextBox Grid.Column="1" Width="100" HorizontalAlignment="Left" Text="{Binding Record.Name,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="2,0,0,1" Grid.RowSpan="2"/>
<TextBlock Text="Company" HorizontalAlignment="Center" Margin="0,2,0,3" Width="51" Grid.RowSpan="2" Grid.Row="1"/>
<TextBox Grid.Column="1" Width="100" HorizontalAlignment="Left" Text="{Binding Record.Company,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="2,2,0,1" Grid.Row="1"/>
<TextBlock Grid.Row="2" Text="Region" HorizontalAlignment="Center" Margin="0,1,0,4" Width="37"/>
<TextBox Grid.Row="2" Grid.Column="1" Width="100" HorizontalAlignment="Left" Text="{Binding Record.Region,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="3,1,0,4"/>
<TextBlock Grid.Column="1" Text="HRA" HorizontalAlignment="Left" Margin="131,-1,0,2" Width="23"/>
<TextBox Grid.Column="1" Width="83" HorizontalAlignment="Left" Text="{Binding Record.HRA,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="162,0,0,1"/>
<TextBlock Grid.Column="1" Text="Basic" HorizontalAlignment="Left" Margin="129,2,0,13" Width="26" Grid.RowSpan="2" Grid.Row="1"/>
<TextBox Grid.Column="1" Width="81" HorizontalAlignment="Left" Text="{Binding Record.Basic,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="162,2,0,3" Grid.Row="1"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="PF" HorizontalAlignment="Left" Margin="144,1,0,5" Width="12"/>
<TextBox Grid.Row="2" Grid.Column="1" Width="100" HorizontalAlignment="Left" Text="{Binding Record.PF,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="162,2,0,1"/>
<TextBlock Grid.Column="1" Text="Salary" HorizontalAlignment="Left" Margin="268,-1,0,1" Width="36"/>
<TextBox Grid.Column="1" Width="100" HorizontalAlignment="Left" Text="{Binding Record.Salary,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" Margin="304,0,0,21" Grid.RowSpan="2"/>
<Button Content="Add" Command="{Binding SubmitCommand }" HorizontalAlignment="Left" Grid.Row="4" Margin="121,4,0,5" Width="44" Grid.Column="1"/>
<ListView x:Name="ListedView" ItemsSource="{Binding Records}" Width="Auto" Grid.Row="5" Margin="38,3,13,36" Grid.ColumnSpan="2">
<ListView.View >
<GridView >
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="Auto" />
<GridViewColumn Header="Company" DisplayMemberBinding="{Binding Company}" Width="Auto"/>
<GridViewColumn Header="Region" DisplayMemberBinding="{Binding Region}" Width="Auto" />
<GridViewColumn Header="HRA" DisplayMemberBinding="{Binding HRA}" Width="Auto" />
<GridViewColumn Header="Basic" DisplayMemberBinding="{Binding Basic}" Width="Auto" />
<GridViewColumn Header="PF" DisplayMemberBinding="{Binding PF}" Width="Auto" />
<GridViewColumn Header="Salary" DisplayMemberBinding="{Binding Salary}" Width="Auto" />
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content="Remove" Margin="1,36,50,150" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ListView},Path=DataContext.SubmitCommand1}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Any help is appreciated in this regard. Thanks
If I understand your issue correctly, you should bind the SelectedItem property of the ListView to be able to edit the currently selected item in the TextBox elements above the ListView:
<ListView SelectedItem="{Binding Record}" ... />
With or without Binding you can do it like this :
if ((sender as ListView).SelectedValue != null)
{
string item = (sender as ListView).SelectedValue.ToString();
SelectedIndex = (sender as ListView).SelectedIndex;
list.Items[SelectedIndex] = "Updated";
}
(I like to add a ContextMenu on my ListViewItems so it is easier for users to modify the specified clicked item) :
<ListView x:Name="list">
<ListView.ContextMenu>
<ContextMenu x:Name="contextmenu">
<MenuItem x:Name="Add" Header="Add" Click="Add_Click"/>
<MenuItem x:Name="Del" Header="Delete" Click="Del_Click"/>
<MenuItem x:Name="Update" Header="Update" Click="Update_Click"/>
</ContextMenu>
</ListView.ContextMenu>
</ListView>

C# WPF MVVM set selected in xaml with calendar type app

I'm relatively new to WPF and MVVM, I have only written one other MVVM application. I would like to create my own calendar app but I'm having trouble setting the selected day.
XAML
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="8*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="3" >
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="<"></TextBlock>
</Button>
<Label HorizontalAlignment="Center" VerticalAlignment="Top" x:Name="CalendarTitle" Content="{Binding Path=DateTitle}" Grid.Column="1"/>
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="3" Grid.Column="2" Content=">"/>
</Grid>
<Grid Grid.Row="1">
<ItemsControl ItemsSource="{Binding Days}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="5" Columns="7" FirstColumn="3"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Grid Background="Transparent" MouseDown="Grid_MouseDown" MouseLeave="Grid_MouseLeave" MouseEnter="Grid_MouseEnter">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Content="{Binding DayNumber}"></Label>
<Label Content="{Binding Message}" VerticalAlignment="Center" HorizontalAlignment="Center"></Label>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
Using ItemsControl and Binding its ItemsSource to an ObservableCollection will work with bringing up data fine, how do I also properly create a SelectedDay attribute?
ViewModel
public class CalendarCellsViewModel : BaseINPC
{
public CalendarCellsViewModel()
{
DateTitle = $"{CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedMonthName(DateTime.Today.Month)} {DateTime.Today.Year}";
for(int i = 1; i <= 31; i++)
{
Days.Add(new CalendarDayData { DayNumber = i, Message = "Test" });
}
}
private string _dateTitle;
public string DateTitle
{
get { return _dateTitle; }
set { SetProperty(ref _dateTitle, value); }
}
private ObservableCollection<CalendarDayData> _days = new ObservableCollection<CalendarDayData>();
public ObservableCollection<CalendarDayData> Days
{
get { return _days; }
set { SetProperty(ref _days, value); }
}
}
Model
public class CalendarDayData : BaseINPC
{
public CalendarDayData()
{
}
public int DayNumber { get; set; }
public int ReminderStart { get; set; }
public int ReminderFrequency { get; set; }
public string Message { get; set; }
private bool _selectedDay = false;
public bool SelectedDay
{
get { return _selectedDay; }
set
{
if (_selectedDay != value)
{
_selectedDay = value;
SetProperty(ref _selectedDay, value);
}
}
}
}
Any tips or good resources I should take a look at?
ItemsControl doesn't support selection. You need to use ListBox for this. With that you can bind the SelectedItem property of your ListBox with SelectedDay property from your ViewModel.
XAML
<ListBox ItemsSource="{Binding Days}" SelectedItem="{Binding SelectedDay}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="5" Columns="7" FirstColumn="3"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch">
<StackPanel Background="Transparent" HorizontalAlignment="Stretch">
<Label Content="{Binding DayNumber}"/>
<Label Content="{Binding Message}" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You can get the SelectedItem by having a property to Bind in your ViewModel. Something like,
ViewModel
public class CalendarCellsViewModel : INotifyPropertyChanged
{
private string _dateTitle;
private ObservableCollection<CalendarDayData> _days;
private CalendarDayData _selectedDay;
public string DateTitle
{
get { return _dateTitle; }
set
{
_dateTitle = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DateTitle)));
}
}
public ObservableCollection<CalendarDayData> Days
{
get { return _days; }
set
{
_days = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Days)));
}
}
public CalendarDayData SelectedDay
{
get { return _selectedDay; }
set
{
_selectedDay = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedDay)));
}
}
public CalendarCellsViewModel()
{
DateTitle = $"{CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedMonthName(DateTime.Today.Month)} {DateTime.Today.Year}";
Days = new ObservableCollection<CalendarDayData>();
for (int i = 1; i <= 31; i++)
{
var day = new CalendarDayData { DayNumber = i, Message = "Test" };
if (i == DateTime.Today.Day)
SelectedDay = day;
Days.Add(day);
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Model
public class CalendarDayData
{
public int DayNumber { get; set; }
public int ReminderStart { get; set; }
public int ReminderFrequency { get; set; }
public string Message { get; set; }
}
Additional
If you want to differentiate your SelectedItem you can set below style to your Label.
<Label Content="{Binding DayNumber}">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Value="True">
<Setter Property="FontWeight" Value="ExtraBold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

wpf collectionview multiple filter

I need some advice. I have two ListViews first ListView is "ListViewAlbums" and the second "ListViewTracks".
 
Items in ListViewTracks are organized into groups.
ListViewAlbums is set SelectionMode = "Extended" and Behaviours: MultiSelectorBehaviours.SynchronizedSelectedItems.
MultiSelectorBehaviours
When I select multiple items from ListViewAlbums, so I want to show all the items in ListViewTracks based ALBUMID.
My current code:
ListViewTracks GroupDescriptions:
PropertyGroupDescription groupDescription = new PropertyGroupDescription("AlbumID");
viewTrack.GroupDescriptions.Add(groupDescription);
viewTrack.SortDescriptions.Add(new System.ComponentModel.SortDescription("AlbumTitle", System.ComponentModel.ListSortDirection.Ascending));
viewTrack.SortDescriptions.Add(new System.ComponentModel.SortDescription("TitleTrack", System.ComponentModel.ListSortDirection.Ascending));
Employees data:
private ObservableCollection<EmployeesAlbums> _listAlbums = new ObservableCollection<EmployeesAlbums>();
public ObservableCollection<EmployeesTracks> _listTrack = new ObservableCollection<EmployeesTracks>();
public ObservableCollection<EmployeesTracks> PlayListTracks
{
get { return _listTrack; }
set { _listTrack = value; RaisePropertyChanged("PlayListTracks"); }
}
public ObservableCollection<EmployeesAlbums> PlayListAlbums
{
get { return _listAlbums; }
set { _listAlbums = value; RaisePropertyChanged("PlayListAlbums"); }
}
EmployeesAlbums model = new EmployeesAlbums
{
IdAlbums = int.Parse(rdr["Id"].ToString()),
TitleAlbum = rdr["TitleAlbums"].ToString(),
ArtistAlbum = rdr["ArtistAlbums"].ToString()
};
modelTracks = new EmployeesTracks
{
IdTrack = int.Parse(rdr["Id"].ToString()),
TitleTrack = rdr["TitleTrack"].ToString(),
PathTrack = rdr["Path"].ToString(),
AlbumTitle = rdr["AlbumTitle"].ToString(),
ArtistTrack = rdr["ArtistTrack"].ToString(),
AlbumID = int.Parse(rdr["AlbumId"].ToString()).ToString()
};
SelectedItem of ListViewAlbums:
SelectionChangedItemsAlbumCommand = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(SelectionChangedItemsAlbum);
private EmployeesAlbums _selectedPlayListFileAlbum;
public EmployeesAlbums SelectedPlayListFileAlbum
{
get { return _selectedPlayListFileAlbum; }
set
{
if (_selectedPlayListFileAlbum != value)
{
_selectedPlayListFileAlbum = value;
RaisePropertyChanged("SelectedPlayListFileAlbum");
}
}
}
private IEnumerable<EmployeesAlbums> _selectedPlayListFilesAlbums;
public IEnumerable<EmployeesAlbums> SelectedPlayListFilesAlbums
{
get { return this.selectedPlayListFilesAlbums; }
set { Set(ref selectedPlayListFilesAlbums, value); }
}
Filtering:
public string AlbumID { get; set; }
void SelectionChangedItemsAlbum()
{
foreach (var items in SelectedPlayListFilesAlbums)
{
ListCollectionView empView = CollectionViewSource.GetDefaultView(PlayListTracks) as ListCollectionView;
// Enable Live Filtering of the ListViewCollection
empView.IsLiveFiltering = true;
// Enable the filtering on AlbumID
empView.LiveFilteringProperties.Add("AlbumID");
AlbumID = items.IdAlbums.ToString();
// Filter based upon AlbumID
empView.Filter = new Predicate<object>(IsMatchFoundAlbums);
// Refresh Collection
empView.Refresh();
}
}
bool IsMatchFoundAlbums(object d)
{
bool res = false;
EmployeesTracks emp = d as EmployeesTracks;
if (emp.AlbumID == AlbumID)
{
res = true;
}
return res;
}
XAML Code:
<ListView x:Name="ListViewTracks"
VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingStackPanel.CacheLength="20,20"
VirtualizingStackPanel.CacheLengthUnit="Item"
ItemsSource="{Binding PlayListTracks}"
Style="{StaticResource CommonListViewStyleTracks}"
ItemContainerStyle="{DynamicResource styleListViewItem}"
>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</GroupStyle.Panel>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" />
<ItemsPresenter Margin="0,0,0,20" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate >
<Grid d:DesignWidth="460" Height="51">
<StackPanel>
<TextBlock DataContext="{Binding Items}" Text="{Binding AlbumTitle}" FontSize="18" TextTrimming="CharacterEllipsis" Foreground="{DynamicResource ItemsListViewForeground}"/>
<TextBlock DataContext="{Binding Items}" Text="{Binding ArtistTrack}" TextTrimming="CharacterEllipsis" Foreground="{DynamicResource AccentColorApps}"/>
</StackPanel>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
<ListView
x:Name="ListViewAlbums"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding PlayListAlbums}"
SelectionMode="Extended"
SelectedItem="{Binding SelectedPlayListFileAlbum,UpdateSourceTrigger=PropertyChanged}" SelectionMode="Extended"
behaviours:MultiSelectorBehaviours.SynchronizedSelectedItems="{Binding SelectedPlayListFilesAlbums, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Background="{x:Null}" Grid.Column="1" Grid.RowSpan="4"
ItemTemplate="{DynamicResource AlbumsDataTemplate}"
BorderBrush="{x:Null}"
>
<ie:Interaction.Triggers >
<ie:EventTrigger EventName="SelectionChanged">
<ie:InvokeCommandAction Command="{Binding SelectionChangedItemsAlbumCommand}"
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}}"/>
</ie:EventTrigger>
</ie:Interaction.Triggers>
</ListView>
Thanks a lot.
Try this
Right after you have initialized the property PlaylistTracks, do:
ListCollectionView empView = CollectionViewSource.GetDefaultView(PlayListTracks) as ListCollectionView;
empView.Filter = IsMatchFoundAlbums;
And let your Match method be:
bool IsMatchFoundAlbums(object d)
{
EmployeesTracks emp = d as EmployeesTracks;
return SelectedPlayListFilesAlbums.Any(x => x.IdAlbums == emp.AlbumID);
}

Not getting value from StackPanel

I have been having a problem with getting the exact value from the stackpanel.
XAML
<Page
x:Class="MedicinesApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MedicinesApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="MedicinesCollectionViewSource" IsSourceGrouped="True" />
</Page.Resources>
<GridView
ItemsSource="{Binding Source={StaticResource MedicinesCollectionViewSource}}"
x:Name="MedicinesGridView"
Padding="30,20,40,0"
SelectionMode="Single"
IsSwipeEnabled="false"
IsItemClickEnabled="True" SelectionChanged="MedicinesGridView_SelectionChanged"
ItemClick="MedicinesGridView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate x:Name="templateTrending">
<Grid HorizontalAlignment="Left" Width="250" Height="250" x:Name="wow">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding Path=DiseaseImageSource}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<StackPanel Orientation="Vertical">
<TextBlock Text="Disease Name" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="30" Margin="15,0,15,0"/>
<TextBlock x:Name="DiseaseNameBro" Text="{Binding Path=DiseaseName, Mode=TwoWay}" Style="{StaticResource TitleTextBlockStyle}" Height="30" Margin="15,0,15,0"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock Text="Category of Disease" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,87,10"/>
<TextBlock Text="{Binding Path=CategoryOfDisease}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text='{Binding Key}' Foreground="Gray" Margin="5" FontSize="30" FontFamily="Segoe UI Light" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid MaximumRowsOrColumns="2" Orientation="Horizontal" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
C#
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.UI.Xaml.Controls;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace MedicinesApp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public string getMedicinesName;
public ObservableCollection<Disease> diseaseList = new ObservableCollection<Disease>();
public MainPage()
{
this.InitializeComponent();
diseaseList.Add(new Disease { DiseaseName = "Malaria", DiseaseImageSource = "/Assets/133px-Malaria.jpg", CategoryOfDisease = "Blood" });
diseaseList.Add(new Disease { DiseaseName = "Typhod", DiseaseImageSource = "../Assets/apple.jpg", CategoryOfDisease = "Thorat" });
diseaseList.Add(new Disease { DiseaseName = "Cancer", DiseaseImageSource = "../Assets/orange.jpg", CategoryOfDisease = "Body" });
diseaseList.Add(new Disease { DiseaseName = "Headache", DiseaseImageSource = "../Assets/bilberry.jpg", CategoryOfDisease = "Brain" });
//diseaseList = new ObservableCollection<Disease>(diseaseList.OrderBy(c => c.DiseaseName));
MedicinesCollectionViewSource.Source = GetGroupsByLetter();
}
internal List<GroupInfoList<object>> GetGroupsByLetter()
{
var groups = new List<GroupInfoList<object>>();
var query = from item in diseaseList
orderby item.DiseaseName
group item by item.DiseaseName[0] into g
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
var info = new GroupInfoList<object>();
info.Key = g.GroupName;
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
public class GroupInfoList<T> : List<object>
{
public object Key { get; set; }
public new IEnumerator<object> GetEnumerator()
{
return base.GetEnumerator();
}
}
public class Disease
{
public string DiseaseName { get; set; }
public string DiseaseImageSource { get; set; }
public string CategoryOfDisease { get; set; }
}
private void MedicinesGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
getMedicinesName = ((Disease)MedicinesGridView.SelectedItem).DiseaseName;
}
private void MedicinesGridView_ItemClick(object sender, ItemClickEventArgs e)
{
this.Frame.Navigate(typeof(malaria), getMedicinesName);
}
}
the problem is whenever I click on Malaria,
it goes to the other page and shows cancer, which is the first vaule in the list.
How can I get the value of the item I click and not of the first item. I Have attached screenshot for you'll to get a better knowledge of things.
I looked at your code and there is one thing that I don't understand.
Why are you using 2 events to navigate. Only one would do the job.
private void MedicinesGridView_ItemClick(object sender, ItemClickEventArgs e)
{
var selectedDisease = e.ClickedItem as Disease;
this.Frame.Navigate(typeof(malaria), selectedDisease);
}
You don't need the getMedicinesName either.
Don't forget to remove the SelectionChanged event both from you code behind and XAML.

Semantic zoom - tap item to navigate to specific page

How can I get my app to navigate to a specific page based on the item within the semantic zoom that was tapped? Each item has a link to its own page and I want to use the 'item.Link' element so that the app reads the link and uses it to navigate to the specified page.
MetropolitanDataSource.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Exits_Expert_London_Lite
{
using System;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
// To significantly reduce the sample data footprint in your production application, you can set
// the DISABLE_SAMPLE_DATA conditional compilation constant and disable sample data at runtime.
#if DISABLE_SAMPLE_DATA
internal class SampleDataSource { }
#else
public class Item : System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
private string _Station = string.Empty;
public string Station
{
get
{
return this._Station;
}
set
{
if (this._Station != value)
{
this._Station = value;
this.OnPropertyChanged("Station");
}
}
}
private string _Zone = string.Empty;
public string Zone
{
get
{
return this._Zone;
}
set
{
if (this._Zone != value)
{
this._Zone = value;
this.OnPropertyChanged("Zone");
}
}
}
private string _Link = string.Empty;
public string Link
{
get
{
return this._Link;
}
set
{
if (this._Link != value)
{
this._Link = value;
this.OnPropertyChanged("Link");
}
}
}
}
public class GroupInfoList<T> : List<object>
{
public object Key { get; set; }
public new IEnumerator<object> GetEnumerator()
{
return (System.Collections.Generic.IEnumerator<object>)base.GetEnumerator();
}
}
public class StoreData
{
public StoreData()
{
Item item;
item = new Item();
item.Station = "Amersham";
item.Zone = "Fare zone 9";
item.Link = "/Lines and Stations/Metropolitan/AMR_(Metropolitan).xaml";
Collection.Add(item);
item = new Item();
item.Station = "Chalfont & Latimer";
item.Zone = "Fare zone 8";
item.Link = "/Lines and Stations/Metropolitan/CFO_(Metropolitan).xaml";
Collection.Add(item);
item = new Item();
item.Station = "Chesham";
item.Zone = "Fare zone 9";
item.Link = "/Lines and Stations/Metropolitan/Chesham.xaml";
Collection.Add(item);
}
private ItemCollection _Collection = new ItemCollection();
public ItemCollection Collection
{
get
{
return this._Collection;
}
}
internal List<GroupInfoList<object>> GetGroupsByCategory()
{
List<GroupInfoList<object>> groups = new List<GroupInfoList<object>>();
var query = from item in Collection
orderby ((Item)item).Zone
group item by ((Item)item).Zone into g
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
GroupInfoList<object> info = new GroupInfoList<object>();
info.Key = g.GroupName;
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
internal List<GroupInfoList<object>> GetGroupsByLetter()
{
List<GroupInfoList<object>> groups = new List<GroupInfoList<object>>();
var query = from item in Collection
orderby ((Item)item).Station
group item by ((Item)item).Station[0] into g
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
GroupInfoList<object> info = new GroupInfoList<object>();
info.Key = g.GroupName;
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
}
// Workaround: data binding works best with an enumeration of objects that does not implement IList
public class ItemCollection : IEnumerable<Object>
{
private System.Collections.ObjectModel.ObservableCollection<Item> itemCollection = new System.Collections.ObjectModel.ObservableCollection<Item>();
public IEnumerator<Object> GetEnumerator()
{
return itemCollection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(Item item)
{
itemCollection.Add(item);
}
}
#endif
}
Metropolitan_line.xaml.cs
using Exits_Expert_London_Lite.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237
namespace Exits_Expert_London_Lite.Lines_and_Stations.Metropolitan
{
public sealed partial class Metropolitan_line : Page
{
public Metropolitan_line()
{
this.InitializeComponent();
StoreData _storeData = null;
// creates a new instance of the sample data
_storeData = new StoreData();
// sets the list of categories to the groups from the sample data
List<GroupInfoList<object>> dataLetter = _storeData.GetGroupsByLetter();
// sets the CollectionViewSource in the XAML page resources to the data groups
cvsMetropolitan.Source = dataLetter;
// sets the items source for the zoomed out view to the group data as well
(semanticZoom.ZoomedOutView as ListViewBase).ItemsSource = cvsMetropolitan.View.CollectionGroups;
(semanticZoom.ZoomedInView as ListViewBase).SelectedIndex = -1;
}
#region Data Visualization
void ItemsGridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
ItemViewer iv = args.ItemContainer.ContentTemplateRoot as ItemViewer;
if (args.InRecycleQueue == true)
{
iv.ClearData();
}
else if (args.Phase == 0)
{
iv.ShowPlaceholder(args.Item as Item);
args.RegisterUpdateCallback(ContainerContentChangingDelegate);
}
else if (args.Phase == 1)
{
iv.ShowStation();
args.RegisterUpdateCallback(ContainerContentChangingDelegate);
}
else if (args.Phase == 2)
{
iv.ShowZone();
}
args.Handled = true;
}
private TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs> ContainerContentChangingDelegate
{
get
{
if (_delegate == null)
{
_delegate = new TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs>(ItemsGridView_ContainerContentChanging);
}
return _delegate;
}
}
private TypedEventHandler<ListViewBase, ContainerContentChangingEventArgs> _delegate;
#endregion //Data Visualization
private void backButton_Tapped(object sender, TappedRoutedEventArgs e)
{
this.Frame.Navigate(typeof(Station_Chooser));
}
void GridView_ItemClicked(object sender, ItemClickEventArgs args)
{
var item = (Item)args.ClickedItem;
if (item.Link == "/Lines and Stations/Metropolitan/AMR_(Metropolitan).xaml")
((Frame)Window.Current.Content).Navigate(typeof(AMR__Metropolitan_));
else if (item.Link == "/Lines and Stations/Metropolitan/CFO_(Metropolitan).xaml")
((Frame)Window.Current.Content).Navigate(typeof(CFO__Metropolitan_));
else if (item.Link == "/Lines and Stations/Metropolitan/Chesham.xaml")
((Frame)Window.Current.Content).Navigate(typeof(Chesham));
}
}
}
ItemViewer.xaml
<UserControl
x:Class="Exits_Expert_London_Lite.ItemViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Exits_Expert_London_Lite"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Margin="0,0,0,20" HorizontalAlignment="Left">
<StackPanel>
<StackPanel Margin="10,0,0,0" Width="420">
<TextBlock x:Name="stationTextBlock" Foreground="{StaticResource ApplicationForegroundThemeBrush}" VerticalAlignment="Center" HorizontalAlignment="Left" FontFamily="Segoe UI" FontSize="32" FontWeight="Light" />
<TextBlock x:Name="zoneTextBlock" TextWrapping="Wrap" Foreground="White" FontSize="20" FontWeight="Light" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
Metropolitan_line.xaml
<Page
x:Class="Exits_Expert_London_Lite.Lines_and_Stations.Metropolitan.Metropolitan_line"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Exits_Expert_London_Lite"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="cvsMetropolitan" IsSourceGrouped="true" />
</Page.Resources>
<Grid Background="Black">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Margin="39,59,39,0"
Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button" Tapped="backButton_Tapped"/>
<TextBlock x:Name="pageTitle" Text="Metropolitan line" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40" Foreground="#FF9B0056"/>
</Grid>
<Grid x:Name="Output" Grid.Row="1">
<!-- This shows a hard-coded width to show within the SDK Sample framework. In a real application you likely wouldn't set a width on the SemanticZoom -->
<SemanticZoom x:Name="semanticZoom" Margin="0,0,0,0">
<SemanticZoom.ZoomedOutView>
<GridView ScrollViewer.IsHorizontalScrollChainingEnabled="False" >
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Group.Key}" HorizontalAlignment="Center" FontFamily="Segoe UI" FontWeight="Light" FontSize="56" Foreground="White"/>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid ItemWidth="200" ItemHeight="200" MaximumRowsOrColumns="4" VerticalAlignment="Center"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="Margin" Value="4" />
<Setter Property="Padding" Value="10" />
<Setter Property="Background" Value="#9B0056" />
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
</GridView.ItemContainerStyle>
</GridView>
</SemanticZoom.ZoomedOutView>
<SemanticZoom.ZoomedInView>
<GridView x:Name="ItemsGridView"
ItemsSource="{Binding Source={StaticResource cvsMetropolitan}}"
ShowsScrollingPlaceholders="False"
ContainerContentChanging="ItemsGridView_ContainerContentChanging"
IsSwipeEnabled="True" ScrollViewer.IsHorizontalScrollChainingEnabled="False" ItemClick="GridView_ItemClicked">
<GridView.ItemTemplate>
<DataTemplate>
<local:ItemViewer/>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text='{Binding Key}' Foreground="#FF9B0056" Margin="5" FontSize="50" FontFamily="Segoe UI" FontWeight="Light" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
</SemanticZoom.ZoomedInView>
</SemanticZoom>
</Grid>
</Grid>
</Page>
Here you go. In your code-behind...
void GridView_ItemClicked(object sender, ItemClickEventArgs args)
{
var item = (Item)args.ClickedItem;
if (item.Link == "/Page_1.xaml")
((Frame)Window.Current.Content).Navigate(typeof (Page_1));
else if (item.Link == "/Page_2.xaml")
((Frame)Window.Current.Content).Navigate(typeof (Page_2));
else if (item.Link == "/Page_3.xaml")
((Frame)Window.Current.Content).Navigate(typeof (Page_3));
}
Best of luck!

Categories