C# WPF DataGridColumn多转换器参数为未设置的值

C# WPF DataGridColumn多转换器参数为未设置的值,c#,wpf,datagrid,C#,Wpf,Datagrid,我的问题总是转换器的第二个参数,即dependencProperty.UnSetValue。我不能解决这个问题。我尝试了很多事情,并在论坛上提出了类似的解决方案,但还是失败了。如果我使用itemscontrol而不是datagrid,就不会有任何问题,代码也可以工作,但我必须使用datagrid <ItemsControl ItemsSource="{Binding Definitions}" DataContext="{Binding Test}"> <ItemsCont

我的问题总是转换器的第二个参数,即
dependencProperty.UnSetValue
。我不能解决这个问题。我尝试了很多事情,并在论坛上提出了类似的解决方案,但还是失败了。如果我使用itemscontrol而不是datagrid,就不会有任何问题,代码也可以工作,但我必须使用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}"/>

这两个专栏很有效。我可以看出这不是绑定数据问题,但我作为参数而不是视图模型属性发送的是转换器中的
未设置值。怎么可能呢?它还继承自
ItemsControl
。我无法将父datacontext绑定到datagrid。我怎样才能解决这个问题?我很高兴得到这方面的帮助。 提前感谢。

我的解决方案基于。创建继承Freezable并声明数据依赖项属性的类:

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=expander”部分。在声明绑定时使用它。下面将扩展器作为第一个元素

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

我的解决方案基于。创建继承Freezable并声明数据依赖项属性的类:

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=expander”部分。在声明绑定时使用它。下面将扩展器作为第一个元素

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

您应该在
DataGridComboBoxColumn
ElementStyle
EditingElementStyle
中设置
ItemsSource
组合框的
属性。然后,您可以使用
相对资源
绑定到
扩展器

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


不要设置
DataGridComboxColumn
本身的
ItemsSource
属性。这将不起作用,因为
DataGridColumn
不是添加到可视化树中的可视化
UIElement
,因此它无法找到
扩展器

您应该在
DataGridComboxColumn
。然后,您可以使用
相对资源
绑定到
扩展器

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


不要设置
DataGridComboxColumn
本身的
ItemsSource
属性。这将不起作用,因为
DataGridColumn
不是添加到可视化树中的可视化
UIElement
,因此由于Ramin,它将无法找到
扩展器。我解决了这个问题,但我不得不做一些改变

文章说,, 我可以将视图模型绑定到代理,如下所示

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


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

多亏了Ramin。我解决了这个问题,但我不得不做一些改变

文章说,, 我可以将视图模型绑定到代理,如下所示

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


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

您不必使用绑定代理。只需设置列的DataGridComboxColumn属性的ElementStyle和EditingElementStyle属性。有关更多信息,请参阅我的答案。您不必使用绑定代理。只需设置列的DataGridComboxColumn属性的ElementStyle和EditingElementStyle属性。有关更多信息,请参阅我的答案。感谢您的帮助和Ramin,它通过一点编辑解决了我的问题。当我在DataGrid资源中定义代理时,我可以访问viewmodel。感谢您的帮助和Ramin,它通过一点编辑解决了我的问题。当我在DataGrid资源中定义代理时,我可以访问viewmodel.Hi mm8,我尝试了您的解决方案。你的回答也是正确的。我检查并从DependencyObject中看到RIT中的列对象,它不像您所说的UIElement。我不知道。谢谢你的回答和帮助。嗨,我试过你的解决方案。你的回答也是正确的。我检查并从DependencyObject中看到RIT中的列对象,它不像您所说的UIElement。我不知道。谢谢你的回答和帮助。