Reputation: 1759
I'm working on a WPF application with a DataGrid which has manually defined columns. In that DataGrid the user shall be able to input data including a lower bound (a decimal value) and a comparer sign ("<" or "<=").
The DataGrid itself is bound to an ObservableCollection named StepDataSource:
/// <summary>
/// Gets or sets the data of the stepfunction.
/// </summary>
public ObservableCollection<StepData> StepDataSource
{
get { return stepdataSource; }
set
{
stepdataSource = value;
RaisePropertyChanged("StepDataSource");
}
}
The class StepData - which is not part of the viewmodel - contains the following properties:
/// <summary>
/// Gets or sets the lower bound.
/// </summary>
public double LowerBound { get; set; }
/// <summary>
/// Gets or sets the assigned value.
/// </summary>
public double StepValue { get; set; }
/// <summary>
/// Gets or sets the lower comparer.
/// </summary>
public ArithmeticSignData LowerComparer2 { get; set; }
The last property LowerComparer2 is needed for the item which was selected in the ComboBox.
One of my columns in the DataGrid is a DataGridComboBoxColumn which is bound to another ObservableCollection in my viewmodel:
public ObservableCollection<ArithmeticSignData> LowerComparers2 { get; set; }
The class ArithmeticSignData contains properties for the key and value which shall be used by the ComboBox.
public class ArithmeticSignData
{
/// <summary>
/// The constructor.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="value">The value.</param>
public ArithmeticSignData(string key, string value)
{
ArithmeticSignKey = key;
ArithmeticSignValue = value;
}
public string ArithmeticSignKey { get; set; }
public string ArithmeticSignValue { get; set; }
}
In the viewmodel i'm filling that collection:
LowerComparers2 = new ObservableCollection<ArithmeticSignData>();
LowerComparers2.Add(new ArithmeticSignData("1", "<"));
LowerComparers2.Add(new ArithmeticSignData("2", "<="));
Then i defined the column in the DataGrid like that:
<DataGrid x:Name="grd_stepdata"
Grid.Row="0"
Grid.Column="0"
Margin="5"
AutoGenerateColumns="False"
CanUserAddRows="True"
CanUserDeleteRows="True"
SelectionUnit="FullRow"
ItemsSource="{Binding StepDataSource, NotifyOnSourceUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Columns>
<DataGridComboBoxColumn x:Name="col_LowerComparer2"
SelectedItemBinding="{Binding LowerComparer2, NotifyOnSourceUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="ArithmeticSignValue"
Header="LowComp"/>
</DataGrid.Columns>
</DataGrid>
By some articles in this forum i have learned that the ItemsSource has to be set in code-behind:
col_LowerComparer2.ItemsSource = vm.LowerComparers2;
When i start the app and select an item i can see in my viewmodel-property LowerComparer2 the selected item with the correct key and value. But unfortunately i cannot see existing data from the viewmodel in the column after i started the app.
Have i forgotten one or more attributes?
Upvotes: 0
Views: 188
Reputation: 169200
Try this:
<DataGridComboBoxColumn x:Name="col_LowerComparer2"
SelectedItemBinding="{Binding LowerComparer2, NotifyOnSourceUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="ArithmeticSignValue"
Header="LowComp">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.LowerComparers2, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.LowerComparers2, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
Also note that the object returned by the LowerComparer2 property of the StepData
object must be present in the LowerComparers2 collection of the MainViewModelClass
for an item to be selected. This means that you can't set this property to a new ArithmeticSignData
object. You should set it to any of the ArithmeticSignData
objects that have already been added to the LowerComparers2 collection:
using System.Linq;
...
public MainWindow()
{
// The window components are initialized.
InitializeComponent();
// DataContext gets the viewmodel.
DataContext = vm;
vm.StepDataSource.Add(new StepData("<", 0, 0, vm.LowerComparers2.FirstOrDefault(x => x.ArithmeticSignKey == "1")));
vm.StepDataSource.Add(new StepData("<=", 0.1, 0.8, vm.LowerComparers2.FirstOrDefault(x => x.ArithmeticSignKey == "2")));
vm.StepDataSource.Add(new StepData("<", 0.2, 1.2, vm.LowerComparers2.FirstOrDefault(x => x.ArithmeticSignKey == "1")));
vm.StepDataSource.Add(new StepData("<=", 0.3, 1.4, vm.LowerComparers2.FirstOrDefault(x => x.ArithmeticSignKey == "2")));
ChartDataRefresh();
...
}
Upvotes: 2