Reputation: 812
My problem is always Converter's second parameter which is DependencyProperty.UnSetValue
. I cannot fix that. I try many things and suggested solution in similar topics in forums but again I failed. If I use itemscontrol instead of datagrid, there is no any problem and code works but I have to use data grid.
<ItemsControl ItemsSource="{Binding Definitions}" DataContext="{Binding Test}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type definitions:Definition}">
<Expander Header="{Binding Name}" x:Name="expander" Width="700" VerticalAlignment="Top" HorizontalAlignment="Left" DataContext="{Binding}" IsExpanded="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
</Grid>
<Grid Grid.Row="1" Margin="0,5,0,0">
<DataGrid DataContext="{Binding Path=DataContext, ElementName=expander}" ItemsSource="{Binding Items}" CanUserAddRows="True" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" IsReadOnly="{Binding Path=AutoNamed,Mode=TwoWay}" />
<DataGridComboBoxColumn DisplayMemberPath="ID" SelectedValuePath="Number" Header="-" SelectedValueBinding="{Binding Path=Start,Mode=TwoWay}">
<DataGridComboBoxColumn.ItemsSource>
<MultiBinding Converter="{StaticResource Converter}">
<Binding Path="Test.Types" Source="{x:Static viewmodels:ApplicationVM.Instance}" />
<Binding Path="DataContext.Name" ElementName="expander" />
</MultiBinding>
</DataGridComboBoxColumn.ItemsSource>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn Header="+" DisplayMemberPath="ID" SelectedValuePath="Number" SelectedValueBinding="{Binding Path=End,Mode=TwoWay}">
<DataGridComboBoxColumn.ItemsSource>
<MultiBinding Converter="{StaticResource Converter}">
<Binding Path="Test.Types" Source="{x:Static viewmodels:ApplicationVM.Instance}" />
<Binding Path="Header" ElementName="expander" />
</MultiBinding>
</DataGridComboBoxColumn.ItemsSource>
</DataGridComboBoxColumn>
<DataGridTextColumn Header="Low" Binding="{Binding Path=Low,Mode=TwoWay}" />
<DataGridTextColumn Header="High" Binding="{Binding Path=High,Mode=TwoWay}" />
<DataGridCheckBoxColumn Header="Auto Name" Binding="{Binding Path=AutoNamed,Mode=TwoWay}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
</Expander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Firstly, I thought it could be the binding issue. So, I added two new column to test.
<DataGridTextColumn Header="Name2" Binding="{Binding Path=Header, ElementName=expander}"/>
<DataGridTextColumn Header="Name3" Binding="{Binding Path=DataContext.Name, ElementName=expander}"/>
These two columns worked. I can see it is not binding data issue, but what I send as parameter instead of view model property is UnSetValue
in Converter. How can it be possible? It is also inherited from ItemsControl
. I can not bind parent datacontext to datagrid. How can I solve this problem? I am glad to get help about it.
Thanks in advance.
Upvotes: 0
Views: 516
Reputation: 812
Thanks to Ramin. I solved the problem, but I have to some changes.
According to Artical, I can bind view-model to proxy like below
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>
And after that,
<DataGridComboBoxColumn Header="+" DisplayMemberPath="ID" SelectedValuePath="Number" SelectedValueBinding="{Binding Path=End,Mode=TwoWay}">
<DataGridComboBoxColumn.ItemsSource>
<MultiBinding Converter="{StaticResource Converter}">
<Binding Path="Test.Types" Source="{x:Static viewmodels:ApplicationVM.Instance}" />
<Binding Path="Data.Name" Source="{StaticResource proxy}" />
</MultiBinding>
</DataGridComboBoxColumn.ItemsSource>
</DataGridComboBoxColumn>
I can reach my view-model over the proxy, so parameters is not UnSetValue anymore.
Upvotes: 0
Reputation: 169360
You should set the ItemsSource
property of the ComboBox
in the ElementStyle
and EditingElementStyle
of the DataGridComboBoxColumn
. You can then use a RelativeSource
to bind to the Expander
:
<DataGrid DataContext="{Binding Path=DataContext, ElementName=expander}" ItemsSource="{Binding Items}"
CanUserAddRows="True" AutoGenerateColumns="False">
<DataGrid.Resources>
<Style x:Key="PlusColumnStyle" TargetType="ComboBox">
<Setter Property="ItemsSource">
<Setter.Value>
<MultiBinding Converter="{StaticResource Converter}">
<!--<Binding Path="Test.Types" Source="{x:Static viewmodels:ApplicationVM.Instance}" />-->
<Binding Path="Header" RelativeSource="{RelativeSource AncestorType=Expander}" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridComboBoxColumn Header="+" DisplayMemberPath="ID" SelectedValuePath="Number"
SelectedValueBinding="{Binding Path=End,Mode=TwoWay}"
ElementStyle="{StaticResource PlusColumnStyle}" EditingElementStyle="{StaticResource PlusColumnStyle}"/>
<!-- + the other columns...-->
</DataGrid.Columns>
</DataGrid>
Don't set the ItemsSource
property of the DataGridComboBoxColumn
itself. This won't work because a DataGridColumn
is not a visual UIElement
that gets added to the visual tree so it won't be able to find the Expander
.
Upvotes: 1
Reputation: 3631
My solution is based on this article. Create a class that inherits Freezable and declares a Data dependency property:
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore() { return new BindingProxy(); }
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy), new UIPropertyMetadata(null));
}
declare an instance of this class as the Expanders resources:
<Expander.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding ElementName=expander}"/>
</Expander.Resources>
Note the "ElementName=expander" part. Use it in declaring the Bindings. The following gives the Expander as the first element.
<MultiBinding Converter="{StaticResource Converter}">
<Binding Source="{StaticResource proxy}" />
</MultiBinding>
Upvotes: 1