Property setter in binding called twice - c#

In order to try to be generic I implemented that WPF and C# Binding in the view but the problem is that the setter of the Value property in the Item class is called two times successively (without passing in any other function - I checked the call stack)
I don't really know if it's a problem of binding or a problem in the code but If you have any idea I would like to hear your feedback.
<DataGrid Grid.Row="1" ItemsSource="{Binding Questions}" AutoGenerateColumns="False" SelectedItem="{Binding Path=DataContext.Answer.QuestionItem, RelativeSource={RelativeSource AncestorType=UserControl}}" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="Questions" Width="SizeTocells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Question}"></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Answers" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" >
<ListView ItemsSource="{Binding Path=DataContext.Answer.Answers, Mode=OneWay, RelativeSource={RelativeSource AncestorType=UserControl}}">
<ListView.ItemTemplate>
<DataTemplate>
<RadioButton GroupName="{Binding Path=GroupName, Mode=OneWay}" Content="{Binding Path=Content, Mode=OneWay}" IsChecked="{Binding Path=Value, Mode=TwoWay}" Margin="0, 0, 10, 0" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
public class Item : BindableBase
{
public string Content { get; }
public string GroupName { get; }
private bool _val;
public bool Value
{
get { return _val; }
set
{
SetProperty(ref _val, value);
}
}
public Item(string content, string groupName, bool value = false)
{
Content = content;
GroupName = groupName;
Value = value;
}
}
public class AnswerModel
{
public List<Item> Answers { get; }
public AnswerModel(List<string> possibleAnswers)
{
Answers = new List<Item>();
for (int i = 0; i < possibleAnswers.Count(); ++i)
{
char c = Convert.ToChar('A' + i);
var letter = Convert.ToString(c);
Answers.Add(new Item(letter, "group" + letter));
}
}
}
public class InsertWordQuestionViewModel : BindableBase, INavigationAware
{
public AnswerModel Answer { get; private set; }
public void OnNavigatedTo(NavigationContext navigationContext)
{
PossibleAnswers = new List<string>() { "A test", "B test2", "C test3"};
Questions = navigationContext.Parameters["questions"] as List<QuestionModel<string, string>>;
Answer = new AnswerModel(PossibleAnswers);
}
}

Value property in the Item class is called two times successively - I guess it happens in different items: one item/RadioButton gets unchecked, and another item/RadioButton gets checked. so value argument should be different for those two consequtive invocations

Related

Cannot bind slider value in DataGridTemplateColumn

I am trying to create a DataGrid with two text columns and a template column as follows:
<UserControl
...
Name="TcpNtcpSliders"
...>
<DataGrid Name="MinTcpDataGrid" AutoGenerateColumns="False" Margin="2" Grid.Row="0"
ItemsSource="{Binding MinTcpRows, ElementName=TcpNtcpSliders, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridTextColumn Header="Structure ID" IsReadOnly="True" Width="Auto"
Binding="{Binding StructureId, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Min. TCP" IsReadOnly="True" Width="Auto" x:Name="MinTcpTextColumn"
Binding="{Binding MinTcpValue, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTemplateColumn Header="Set Min. Tcp" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Slider Minimum="0" Maximum="1"
Value="{Binding MinTcpValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</UserControl>
In the code behind I have
internal ObservableCollection<MinTcpRow> MinTcpRows
{
get { return (ObservableCollection<MinTcpRow>)GetValue(MinTcpRowsProperty); }
set { SetValue(MinTcpRowsProperty, value); }
}
internal static readonly DependencyProperty MinTcpRowsProperty =
DependencyProperty.Register("MinTcpRows", typeof(ObservableCollection<MinTcpRow>),
typeof(RtpOptimizationTcpNtcpSliders),
new PropertyMetadata(new ObservableCollection<MinTcpRow>(), MinTcpRowsPropertyChangedCallback));
private static void MinTcpRowsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (RtpOptimizationTcpNtcpSliders)d;
control.MinTcpRows = (ObservableCollection<MinTcpRow>)e.NewValue;
control.CreateTcpNtcpLimits();
}
and the MinTcpRow class is defined like:
public class MinTcpRow
{
public string StructureId { get; }
public double MinTcpValue { get; set; }
public MinTcpRow(string structureId, double minTcpValue)
{
if (minTcpValue < 0 || minTcpValue > 1)
throw new ArgumentOutOfRangeException($"{nameof(minTcpValue)} must " +
$"be in range [0, 1], but was {minTcpValue}.");
StructureId = structureId ?? throw new ArgumentNullException(nameof(structureId));
MinTcpValue = minTcpValue;
}
}
Everything works as expected, except for the Slider value binding. I says cannot resolve symbol 'MinTcpValue'. How can I bind the slider's value correctly?
In order to see what happens I put a simplified version together.
In my mainwindow I have a datagrid:
<DataGrid Name="MinTcpDataGrid" AutoGenerateColumns="False"
ItemsSource="{Binding Rows}">
<DataGrid.Columns>
<DataGridTextColumn Header="Structure ID" IsReadOnly="True" Width="Auto"
Binding="{Binding StructureId, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTextColumn Header="Min. TCP" IsReadOnly="True" Width="Auto" x:Name="MinTcpTextColumn"
Binding="{Binding MinTcpValue, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTemplateColumn Header="Set Min. Tcp" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Slider Minimum="0" Maximum="1"
Value="{Binding MinTcpValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
MainWindowViewModel will supply my Rows collection:
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private ObservableCollection<MinTcpRow> rows = new ObservableCollection<MinTcpRow>();
public MainWindowViewModel()
{
rows.Add(new MinTcpRow ("A",0.1));
rows.Add(new MinTcpRow("B", 0.5));
rows.Add(new MinTcpRow("C", 0.9));
}
}
And MinTcpRow ( is faulted because it won't notify change ) but looks the same.
public class MinTcpRow
{
public string StructureId { get; }
public double MinTcpValue { get; set; }
public MinTcpRow(string structureId, double minTcpValue)
{
if (minTcpValue < 0 || minTcpValue > 1)
throw new ArgumentOutOfRangeException($"{nameof(minTcpValue)} must " +
$"be in range [0, 1], but was {minTcpValue}.");
StructureId = structureId ?? throw new ArgumentNullException(nameof(structureId));
MinTcpValue = minTcpValue;
And that works, no error anyhow. There is a memory leak waiting to catch you out because of not implementing inpc but I get no error like you show us. Are you somehow using a different version of MinTcpRow ?

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.

Add a New Row to DataGrid when user press Enter Key on the last Cell of Last Row

I have a DataGrid having 3 columns.
I want to add a new row to DataGrid when user hits Enter on the last cell of DataGrid. I have successfully done everything as required using DataGrid.InputBindings, But the problem here is that when I presss Enter key on 2nd Column, a new row is added. I want it to be added when focus is on a cell which belong's to 3rd column and I press enter.
Here is my code :
<DataGrid CanUserAddRows="False" CanUserDeleteRows="True" CanUserReorderColumns="False" CanUserResizeColumns="False" AutoGenerateColumns="False"
ItemsSource="{Binding People}" SelectedItem="{Binding SelectedRow}" CurrentCell="{Binding SelectedCell, Mode=OneWayToSource}"
DataGridCell.GotFocus="DataGrid_CellGotFocus" SelectionMode="Single">
<DataGrid.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</DataGrid.InputBindings>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Confirmation" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding DataContext.SelectedConfirmation, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Visibility="{Binding DataContext.ConfirmationVisibility, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource boolToVisibilityConverter}}">
<ComboBox.Items>
<sys:String>Add New</sys:String>
<sys:String>End Of List</sys:String>
</ComboBox.Items>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Name" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Name}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Age" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age}"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And In View-Model :
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
People = new ObservableCollection<Person>();
People.Add(new Person());
NewRowCommand = new RelayCommand(NewRow);
}
private ObservableCollection<Person> _people;
public ObservableCollection<Person> People
{
get
{
return _people;
}
set
{
_people = value;
OnPropertyChanged("People");
}
}
private Person _selectedRow;
public Person SelectedRow
{
get
{
return _selectedRow;
}
set
{
_selectedRow = value;
OnPropertyChanged("SelectedRow");
if (_selectedRow == People.Last())
{
ConfirmationVisibility = true;
}
else
{
ConfirmationVisibility = false;
}
}
}
private bool _confirmationVisibility;
public bool ConfirmationVisibility
{
get
{
return _confirmationVisibility;
}
set
{
_confirmationVisibility = value;
OnPropertyChanged("ConfirmationVisibility");
}
}
private string _selectedConfirmation;
public string SelectedConfirmation
{
get
{
return _selectedConfirmation;
}
set
{
_selectedConfirmation = value;
OnPropertyChanged("SelectedConfirmation");
}
}
private DataGridCellInfo _selectedCell;
public DataGridCellInfo SelectedCell
{
get
{
return _selectedCell;
}
set
{
_selectedCell = value;
OnPropertyChanged("SelectedCell");
}
}
public ICommand NewRowCommand { get; set; }
private void NewRow(object obj)
{
if (SelectedRow == People.Last())
{
if (SelectedConfirmation == "Add New")
{
if (SelectedCell.Column.Header.ToString() == "Age")
{
People.Add(new Person());
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here is the Sample Project created in VS2012 : https://drive.google.com/file/d/0B5WyqSALui0bWVNHcVFXU1hOQ00/edit?usp=sharing
The problem with the code is with the CurrentCell property binding.
it binds the new current cell before NewRowCommand is called.
Lets assume you where on "Name" column on the last row, so what happens is:
You press the enter key.
Current cell is updated with the new cell. (Age)
Then your command is called, and uses the the new current cell(Age) and therefore adds new row.
I would suggest keeping a reference to the previous cell upon currentcell update. and using it instead of currentCell.
public DataGridCellInfo SelectedCell
{
get
{
return _selectedCell;
}
set
{
_lastCell = _selectedCell; //here is my edit
_selectedCell = value;
OnPropertyChanged("SelectedCell");
}
}
So the new NewRow(object obj) looks like this:
private void NewRow(object obj)
{
if (SelectedRow == People.Last())
{
if (SelectedConfirmation == "Add New")
{
if (_lastCell.Column !=null && _lastCell.Column.Header.ToString() =="Age")//here is my edit
{
People.Add(new Person());
}
}
}
}
Also there is a problem inside DataGrid_CellGotFocus(object sender, RoutedEventArgs e). take a look at my edit, i dropped the row.IsSelected assinment.
private void DataGrid_CellGotFocus(object sender, RoutedEventArgs e)
{
// Lookup for the source to be DataGridCell
if (e.OriginalSource.GetType() == typeof(DataGridCell))
{
// Starts the Edit on the row;
DataGrid grd = (DataGrid)sender;
grd.BeginEdit(e);
Control control = GetFirstChildByType<Control>(e.OriginalSource as DataGridCell);
if (control != null)
{
control.Focus();
}
DataGridCell cell = GetDataGridCell(grd.CurrentCell);
DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
if (dataGrid != null)
{
if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
{
if (!cell.IsSelected)
cell.IsSelected = true;
}
}
}
}
I ran the edited code on my pc, it works great! let me know if there are any issues I might have missed.
Any UIElement can have InputBindings, not just DataGrid. So why not move
<DataGrid.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</DataGrid.InputBindings>
To the column you would like:
<DataGridTemplateColumn Header="Age" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Age}">
<TextBlock.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</TextBlock.InputBindings>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding Age}">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding DataContext.NewRowCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
</TextBox.InputBindings>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
When You Press enter then it instantly travels to 3rd column also So instead of creating column when you Selected header == Age create it when it equals Confirmation.
Here is your modified working code to fix the error
private void NewRow(object obj)
{
if (SelectedRow == People.Last())
{
if (SelectedConfirmation == "Add New")
{
if (SelectedCell.Column.Header.ToString() == "Confirmation")
{
People.Add(new Person());
}
}
}
}
Just do this and your sample worked with new row being created when user presses enter on last column.
Hope you got your problem solved and earned myself my first answer and points also.

Datagrid column headers and values binding

I'm having a problem with binding columns headers and values to data grid in MVVM PRISM.
I'm having class SearchResult that has two properties :
ColumnNames ---> those will apply to headers
ColumnValues ---> those will apply to specific headers as their values.
public class SearchResult
{
public List ColumnNames;
public List<object> ColumnValues;
public string ColumnName { get; set; }
public object ColumnValue { get; set; }
public SearchResult()
{
this.ColumnNames = new List<string>();
this.ColumnValues = new List<object>();
}
public void AddColumnAttributes(string columnName, object columnValue)
{
this.ColumnNames.Add(columnName);
this.ColumnValues.Add(columnValue);
this.ColumnName = columnName;
this.ColumnValue = columnValue;
}
}
those properties are lists that are populated dynamically through C# code.
And I need to bind them to columns headers and columns values in XAML.
I've already created ObservableCollection Result which is the source of my gridview, but still is doesn't bind headers and values.
public ObservableCollection<SearchResult> Result
{
get { return this.searchResult; }
set
{
this.searchResult = value;
this.NotifyPropertyChanged("SearchResult");
}
}
And XAML:
<DataGrid ItemsSource="{Binding SearchResult}" Width="350">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock Text="{Binding ColumnName, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"></TextBlock>
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I'll appreciate any help with this!!!
I thick your code should be like this..
<DataGrid ItemsSource="{Binding SearchResult, ElementName=PageTitle}" Width="350">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock Text="{Binding ColumnNames/ColumnName, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"></TextBlock>
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

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