WPF DataBinding问题:DataGrid中的UserControls不绑定

时间:2016-12-28 21:35:26

标签: wpf xaml datagrid user-controls contentcontrol

我正在尝试构建一个DataGrid控件来管理属性网格。我有一个我的参数基类的抽象类,各种类型的参数实现。此基类包含跨每个参数共享的变量(如Group,Name,IsLocked等),然后每个参数管理与特定类型相关的信息。例如,数字参数可以使用滑块进行用户控制,然后使用最小/最大值等。

我已经设置了一个类,它是我的基本参数的Observable Collection,并将其建立为CollectionViewSource的静态资源:

<UserControl.Resources>
    <local:Parameters x:Key="Parameters"/>
    <CollectionViewSource x:Key="cvsParameters" Source="{StaticResource Parameters}" />
</UserControl.Resources>

然后在我的DataGrid中,我使用样式触发器在我的每个参数的用户控件之间切换:

<DataGrid x:Name="DataGrid_Globals"
          ItemsSource="{Binding Source={StaticResource cvsParameters}}"
          AutoGenerateColumns="False"
          CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Key" Binding="{Binding Key}" IsReadOnly="True"/>
        <DataGridTemplateColumn Width="*" >
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <ContentControl>
                        <ContentControl.Style>
                            <Style TargetType="ContentControl">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding UIType}" Value="Text">
                                        <Setter Property="ContentTemplate">
                                            <Setter.Value>
                                                <DataTemplate>
                                                    <controls:ucText DataContext="{Binding}"/>
                                                </DataTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding UIType}" Value="Number">
                                        <Setter Property="ContentTemplate">
                                            <Setter.Value>
                                                <DataTemplate>
                                                    <controls:ucNumber DataContext="{Binding}"/>
                                                </DataTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </ContentControl.Style>
                    </ContentControl>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

我的用户控件的设置是在XAML中声明的数据上下文:

<UserControl.DataContext>
    <local:TestNumber_cls/>
</UserControl.DataContext>
<Grid HorizontalAlignment="Stretch">
    <Slider 
        Value="{Binding NumberValue}" 
        Minimum="{Binding Min}" 
        Maximum="{Binding Max}" 
        />
</Grid>

我无法弄清楚如何确保我的usercontrols正确绑定。我的其他列工作正常,每个Key值出现,正确绑定和更新(对于此示例,它只是&#34; Key&#34;列,但基类中的所有字段都表现得很好。)也可以根据UIType DataTrigger选择正确的UserControl,但是UserControl只是从空构造函数实例化而且不会绑定。

我还确认我的UserControls的独立实例工作正常并正确绑定。例如,当我从后面的代码设置datacontext时(我不想做),它可以工作:

this.OneOffNumberUserControl.DataContext = ((Parameters)this.ParameterGrid.Resources["Parameters"])[2];

我还试图删除DataContext =&#34; {Binding}&#34;来自我的用户控件,但这并没有改变任何内容。

2 个答案:

答案 0 :(得分:1)

结合上面的Mechanic建议,它大大简化了我的属性网格的XAML,通过进一步的研究,我还了解到我需要为每个子类依赖的usercontrol实现DependencyProperty。在我的属性网格UserControl中为每个DataType设置DataTemplate的地方,我将绑定设置为我的DependencyProperty。

<UserControl.Resources>
    <local:Parameters x:Key="Parameters"/>
    <CollectionViewSource x:Key="cvsParameters" Source="{StaticResource Parameters}" />
    <DataTemplate DataType="{x:Type local:TestText_cls}">
        <controls:ucText TextObject="{Binding}"/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:TestNumber_cls}">
        <controls:ucNumber NumberObject="{Binding}"/>
    </DataTemplate>
</UserControl.Resources>
<Grid>
    <DataGrid x:Name="DataGrid_Globals"
                ItemsSource="{Binding Source={StaticResource cvsParameters}}"
                AutoGenerateColumns="False"
                CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Key" Binding="{Binding Key}" IsReadOnly="True"/>
            <DataGridTemplateColumn Width="*" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

然后在我的UserControls后面的代码中,我实现了DependencyProperty:

public static readonly DependencyProperty TextObjectProperty =
    DependencyProperty.Register("TextObject",
        typeof(TestText_cls),
        typeof(ucText),
        new PropertyMetadata(new TestText_cls()));

[Bindable(true)]
public TestText_cls TextObject
{
    get { return (TestText_cls)this.GetValue(TextObjectProperty); }
    set { this.SetValue(TextObjectProperty, value); }
}

public ucText()
{
    InitializeComponent();
}

最后,在每个UserControl中,我确保给它一个名字,然后在我的DependencyProperty中将我的绑定设置为正确的变量:

<UserControl x:Class="Testing.ucText"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Testing.Classes"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             Name="TextUI">
    <Grid HorizontalAlignment="Stretch">
        <TextBox Text="{Binding ElementName=TextUI, Path=TextObject.Value}"/>
    </Grid>
</UserControl>

我希望这可以帮助其他人!

答案 1 :(得分:0)

如果要为不同的子类设置不同的控件,请指定不同的datatemplates,然后

<!--  subtype-specific column  -->
                            <DataGridTemplateColumn Header="">
                                <DataGridTemplateColumn.CellTemplate>
                                    <DataTemplate>
                                        <ContentPresenter Content="{Binding}" />
                                    </DataTemplate>
                                </DataGridTemplateColumn.CellTemplate>
                            </DataGridTemplateColumn>