WPF DataGridColumn MultiConverter参数是UnSetValue

时间:2017-02-07 08:24:03

标签: c# wpf datagrid

我的问题始终是Converter的第二个参数DependencyProperty.UnSetValue。我无法解决这个问题。我尝试了很多东西并在论坛中提出类似主题的解决方案,但我又失败了。如果我使用itemscontrol而不是datagrid,没有任何问题,代码可以工作,但我必须使用数据网格。

<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>

首先,我认为这可能是具有约束力的问题。所以,我添加了两个新列进行测试。

<DataGridTextColumn Header="Name2" Binding="{Binding Path=Header, ElementName=expander}"/>
<DataGridTextColumn Header="Name3" Binding="{Binding Path=DataContext.Name, ElementName=expander}"/>

这两个专栏有效。我可以看到它不是绑定数据问题,但我在Converter中发送的参数而不是视图模型属性是UnSetValue。怎么可能?它也继承自ItemsControl。我无法将父datacontext绑定到datagrid。我怎么解决这个问题?我很高兴得到它的帮助。 提前谢谢。

3 个答案:

答案 0 :(得分:1)

我的解决方案基于this article。创建一个继承Freezable的类并声明一个Data依赖属性:

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

将此类的实例声明为Expanders资源:

<Expander.Resources>
      <local:BindingProxy x:Key="proxy" Data="{Binding ElementName=expander}"/>
</Expander.Resources>

请注意“ElementName = expandder”部分。用它来声明Bindings。以下将Expander作为第一个元素。

<MultiBinding Converter="{StaticResource Converter}">
      <Binding Source="{StaticResource proxy}"  />
</MultiBinding>

答案 1 :(得分:1)

您应该在ItemsSource的{​​{1}}和ComboBox中设置ElementStyle的{​​{1}}属性。然后,您可以使用EditingElementStyle绑定到DataGridComboBoxColumn

RelativeSource

不要设置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> 属性。这不起作用,因为ItemsSource不是可视化DataGridComboBoxColumn,会被添加到可视树中,因此无法找到DataGridColumn

答案 2 :(得分:0)

感谢Ramin。我解决了这个问题,但我必须做一些改变。

根据Artical, 我可以将视图模型绑定到代理,如下所示

<DataGrid.Resources>
    <local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>

之后,

<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>

我可以通过代理访问我的视图模型,因此参数不再是UnSetValue。