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
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.
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>
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>
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;
}
}
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.