ListViewItem with CheckBox IsChecked Binding to ViewModel - c#

I have a ListView with a DataTemplate for displaying for each ListViewItem a Checkbox.
<ListView ItemsSource="{Binding TableNames}">
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Mode=TwoWay}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The ItemsSource ("TableNames") is deklared in the ViewModel like this:
private ObservableCollection<Item> _TableNames = new ObservableCollection<Item>();
public ObservableCollection<Item> TableNames
{
get { return _TableNames; }
set
{
_TableNames = value;
OnPropertyChanged("TableNames");
}
}
public class Item
{
public bool IsSelected { get; set; }
public string Name { get; set; }
public override string ToString()
{
return this.Name;
}
}
How can I bind the IsChecked from the Checkbox to the Item.IsSelected property?
My code doesn't work.

Try this
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" />
</DataTemplate>

Remove RelativeSource
<CheckBox Content="{Binding}" IsChecked="{Binding IsSelected}" />
Since DataContext of ListViewItem will be set to instance of Item all you need to specify is path to IsSelected

Related

Same value gets selected in all comboboxes upon changing selection in one combobox in a WPF application

Hi I have a problem with binding in two cascading comboboxes. Please see below xaml code:
<DataGridTemplateColumn Width="2*" Header="Modality">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox UseLayoutRounding="True" FontFamily="{StaticResource
SiemensSansFontFamily}" FontSize="15" FontWeight="Regular"
Style="{StaticResource InputDataOrderGridComboBoxStyle}"
Margin="10 15 10 15"
Foreground="{StaticResource WhiteOpacityNinetyPercentage}"
VerticalAlignment="Top" Height="30"
Text="{Binding Modality, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding DataContext.Modalities, Mode=TwoWay,
RelativeSource={RelativeSource FindAncestor, AncestorType=
{x:Type DataGrid }}}" DisplayMemberPath="Name"
SelectedItem="{Binding DataContext.SelectedModality,Mode
=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="4*" Header="Image Type">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Name="CmbImageType" UseLayoutRounding="True" FontFamily="{StaticResource SiemensSansFontFamily}" FontSize="15"
FontWeight="Regular" Style="{StaticResource InputDataOrderGridComboBoxStyle}" Margin="10 15 10 15"
Foreground="{StaticResource WhiteOpacityNinetyPercentage}" VerticalAlignment="Top" Height ="30"
Text="{Binding ImageType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding DataContext.ImageTypes, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}"
SelectedItem="{Binding DataContext.SelectedImageType, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}">
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
how my datagrid looks:https://i.stack.imgur.com/5lYtw.png
In View model:
public ObservableCollection Modalities { get; set; }
private ObservableCollection<string> myImageTypes;
public ObservableCollection<string> ImageTypes {
get => myImageTypes;
set
{
myImageTypes = value;
OnPropertyChanged();
}
}
private Modality mySelectedModality;
public Modality SelectedModality
{
get => mySelectedModality;
set
{
mySelectedModality = value;
OnPropertyChanged();
ImageTypes = SelectedModality.ImageTypes;
OnPropertyChanged("ImageTypes");
SelectedImageType = ImageTypes[0];
OnPropertyChanged("SelectedImageType");
}
}
In View model constructor:
Modalities = Modality.GetModalitiesList();
ImageTypes = Modalities[0].ImageTypes;
On adding new row:
Modalities = Modality.GetModalitiesList();
ImageTypes = Modalities[0].ImageTypes;
Model:
public class Modality
{
public string Name { get; set; }
public ObservableCollection<string> ImageTypes { get; private set; }
public static ObservableCollection<Modality> GetModalitiesList()
{
var modalities = new ObservableCollection<Modality> {
new Modality{ Name = "NM", ImageTypes = new ObservableCollection<string>
{
"Static",
"Dynamic",
"Gated",
"WholeBody",
"Tomo",
"Gated Tomo",
"Dynamic Tomo",
"Recon Tomo",
"Gated Recon Tomo",
"Dynamic Recon Tomo" }},
new Modality{ Name = "PT", ImageTypes = new ObservableCollection<string>
{
"Recon Tomo",
"Recon Gated Tomo",
"Recon Dynamic Tomo", }},
new Modality{ Name = "CT", ImageTypes = new ObservableCollection<string>
{
"Any"}}
};
return modalities;
}
}
The Problem is when I select any value in any ImageType combox, same value is shown in all Image type comboboxes.
Please help , how to fix this. Any input is much appreciated. Thanks.

WPF ComboBox SelectionChanged command not firing

I have a ComboBox,and I define its ItemTemplate.I want the combobox selectionChanged command firing when clicking the combobox item or check/uncheck the checkbox before it.Here is the xmal:
<ComboBox x:Name="DeptComboBox"
Grid.Row="2" Grid.Column="3"
IsReadOnly="True"
StaysOpenOnEdit="True"
ItemsSource="{Binding DeptDtoes}"
Text="{Binding SelectedDeptNames}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding DeptSelectedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And the ViewModel:
public class AddDoctorViewModel:ViewModelBase, ISingletonDependency
{
private readonly IBasicAppService _basicAppService;
public ObservableCollection<DeptDto> DeptDtoes { get; }
private string _selectedDeptNames;
public string SelectedDeptNames
{
get { return _selectedDeptNames; }
set
{
_selectedDeptNames = value;
RaisePropertyChanged(nameof(SelectedDeptNames));
}
}
private int _selectedIndex;
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
RaisePropertyChanged(nameof(SelectedIndex));
}
}
public RelayCommand DeptSelectedCommand { get; set; }
public AddDoctorViewModel(IBasicAppService basicAppService)
{
_basicAppService = basicAppService;
DeptDtoes = new ObservableCollection<DeptDto>(_basicAppService?.DeptDtoes);
DeptSelectedCommand = new RelayCommand(DeptSelected);
}
private void DeptSelected()
{
}
}
But the combobox selectionChanged command not firing.Can anyone help me?
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}"
Command="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ComboBox}},Path=DataContext.DeptSelectedCommand}" />
</DataTemplate>
</ComboBox.ItemTemplate>

TabItem Content IsEnabled binding

I'm creating a WPF application using MVVM pattern (at least I'm trying). There is <TabControl> with bound ItemsSource,which is an ObservableCollection<TabModel> Tabs. Tabs has Name and Items property, where Items is a list of ControlModel, which means Controls. I have problem with binding IsEnabled property to Grid where Items are placed.
Below there is a part of my code presenting the way I'm doing this:
private ObservableCollection<TabModel> tabs;
public ObservableCollection<TabModel> Tabs
{
get
{
if (tabs == null)
{
tabs = new ObservableCollection<TabModel>();
RefreshTabs();
}
return tabs;
}
set
{
tabs = value;
OnPropertyChanged("Tabs");
}
}
\\Tab Model
public string Name { get; set; }
private List<ControlModel> items;
public List<ControlModel> Items
{
get { return items; }
set
{
items = value;
OnPropertyChanged("Items");
}
}
And xaml...
<TabControl Margin="0,100,0,0" ItemsSource="{Binding Tabs,UpdateSourceTrigger=PropertyChanged}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<Grid Margin="5,5,5,5" IsEnabled="{Binding IsProductEditionEnabled}">
<!--<Grid Margin="5,5,5,5">-->
<ItemsControl ItemsSource="{Binding Items,UpdateSourceTrigger=PropertyChanged}" ItemTemplateSelector="{StaticResource ControlTemplateSelector}"/>
</Grid>
</ScrollViewer>
</DataTemplate>
</TabControl.ContentTemplate>
The part...
<Grid Margin="5,5,5,5" IsEnabled="{Binding IsProductEditionEnabled}">
is not working. There is no error. This grid is always disabled. By default it's false.
private bool isProductEditionEnabled = false;
public bool IsProductEditionEnabled
{
get { return isProductEditionEnabled; }
set
{
isProductEditionEnabled = value;
OnPropertyChanged("IsProductEditionEnabled");
}
}
The question is : How to bind IsEnabled in my case properly?
You are inside a DataTemplate so you need to specify where the parent DataContext is when you do the binding, something like this:
<DataTemplate>
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<Grid IsEnabled="{Binding Path=DataContext.IsProductEditionEnabled,
RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}">
</Grid>
</ScrollViewer>
</DataTemplate>

C# Caliburn.Micro Multiple selection

I am using Caliburn.Micro in my C# WPF project and I have sucessfully used single selection binding in ListBox. How to use multiple selection in this scenario?
Xaml:
<ListBox x:Name="Items">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Time}"/>
<Label Content="{Binding Desc}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code:
public BindableCollection<MyObject> Items
{
get
{
var collection = new BindableCollection<MyObject>(_MyObject);
return collection;
}
}
public MyObject SelectedItem
{
get; set;
}
Add IsSelected property to your item:
public class MyObject : PropertyChangedBase
{
public DateTime Time { get; set; }
public String Desc { get; set; }
bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
NotifyOfPropertyChange();
}
}
}
Then add binding to this property to your ListBox:
<ListBox x:Name="Items" SelectionMode="Multiple">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Time}"/>
<Label Content="{Binding Desc}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
After that you may refer to selected items in your View Model:
BindableCollection<MyObject> _items = new BindableCollection<MyObject>();
public BindableCollection<MyObject> Items
{
get
{
return _items;
}
}
public BindableCollection<MyObject> SelectedItems
{
get
{
_selectedItems.Clear();
_selectedItems.AddRange(Items.Where(mo => mo.IsSelected));
return _selectedItems;
}
}

ComboBox binding to select item based on equality of properties of two sources when using datatemplate

Please note:
The two types in the lists are simplified a lot for this example and must be kept separate.
The use of an int as connection between the types can not be changed.
The problem:
Given the code below, how do I get the ComboBox marked with ??? to:
Display the ColorDefs.Name as its content.
Set SelectedItem to the one where Models.DisplayColorNumber is equal to ColorDefs.ColorNumber.
Update the Models.DisplayColorNumber updated if the selection is changed.
In code-behind
public List<ModelData> Models { get; }
public List<DisplayColorDefinition> ColorDefs { get; }
DataContext=this;
XAML:
<ListBox ItemsSource="{Binding Models}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox ??? />
<TextBlock Text="{Binding Models, Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
ModelData type:
public class ModelData
{
private string name;
private int displayColorNumber;
public string Name
{
get { return name; }
set { name = value; }
}
public int DisplayColorNumber
{
get { return displayColorNumber; }
set { displayColorNumber = value; }
}
}
DisplayColorDefinition type:
public class DisplayColorDefinition
{
private int colorNumber;
private string name;
private Color displayColor;
public int ColorNumber
{
get { return colorNumber; }
set { colorNumber= value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public Color DisplayColor
{
get { return displayColor; }
set { displayColor = value; }
}
}
Use the SelectedValue and SelectedValuePath :
<ListBox ItemsSource="{Binding Models}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding Path=DataContext.ColorDefs, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
DisplayMemberPath="Name"
SelectedValue="{Binding Path=DisplayColorNumber}"
SelectedValuePath="ColorNumber"
/>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding DisplayColorNumber}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
SelectedValue will be the property on the Model object, and SelectedValuePath will indicate which property of the DisplayColorDefinition to use for the binding.

Categories