将依赖项属性绑定到自定义控件

时间:2014-08-07 19:56:06

标签: c# wpf xaml wpf-controls custom-controls

我正在研究一种大量使用数据网格的WPF应用程序。我经常出现这种情况,需要我在数据网格中使用自定义控件。当然,每行绑定的数据都不同。

我解决这个问题的方法是创建一个类型为DataGridTemplateColumn的自定义控件,并为其添加自己的依赖项属性。然后,当我需要在网格中使用此列类型时,我可以在一行中完成。

似乎自定义控件的数据上下文完全没有了。

现在,我有以下代码......

DataGridCheckedComboColumn.xaml

<DataGridTemplateColumn x:Class="DataTracker.Presentation.GridControls.Views.DataGridCheckedComboColumn"
                        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:ccb="clr-namespace:CheckedComboBoxControl;assembly=CheckedComboBox"
                        mc:Ignorable="d">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ccb:CheckedComboBox ItemsSource="{Binding Path=ComboSource}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ccb:CheckedComboBox ItemsSource="{Binding Path=ComboSource}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

这是代码背后的......

DataGridCheckedComboColumn.xaml.cs

namespace DataTracker.Presentation.GridControls.Views
{
    /// <summary>
    /// Interaction logic for DataGridCheckedComboColumn.xaml
    /// </summary>
    public partial class DataGridCheckedComboColumn : DataGridTemplateColumn
    {
        public DataGridCheckedComboColumn()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Gets or sets the runway data.
        /// </summary>
        /// <value>The runway data.</value>
        public IEnumerable<Object> ComboSource
        {
            get
            {
                return (IEnumerable<Object>)this.GetValue(ComboSourceProperty);
            }
            set
            {
                this.SetValue(ComboSourceProperty, value);
            }
        }

        private static void OnComboSourceChanged(DependencyObject dependentView, DependencyPropertyChangedEventArgs e)
        {
            /////////////////////////////////////////////////////////////////
            //                                                             //
            // This is the code I used when I was making user controls and //
            // sending data to the view models                             //
            //                                                             //
            //                                                             //
            // Not sure what, if anything to do here now...                //
            //                                                             //
            /////////////////////////////////////////////////////////////////

            //var control = (DataGridComboColumn)dependentView;
            //var viewModel = (DataGridComboColumnViewModel)control.DataContext;

            //viewModel.ComboSource = (IEnumerable<Object>)e.NewValue;
        }

        public static readonly DependencyProperty ComboSourceProperty =
            DependencyProperty.Register("ComboSource",
                typeof(IEnumerable<Object>),
                typeof(DataGridCheckedComboColumn),
                new FrameworkPropertyMetadata()
                {
                    PropertyChangedCallback = OnComboSourceChanged,
                    BindsTwoWayByDefault = true
                });

    }
}

我将自定义控件添加到我的数据网格中,如此...

<gc:DataGridCheckedComboColumn ComboSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=DataContext.DataVersions}" />

所有内容都适当呈现,但无论我通过什么数据,都没有任何成功。我甚至硬编码列表并发送了这些,但没有运气。我也尝试过发送其他简单的属性,比如字符串,但也失败了。

WPF出现以下错误。我应该指出,“GenericGridObject”就是我用。填充完整数据网格的内容。

System.Windows.Data Error: 40 : BindingExpression path error: 'ComboSource' property not found on 'object' ''GenericGridObject`1' (HashCode=37030675)'. BindingExpression:Path=ComboSource; DataItem='GenericGridObject`1' (HashCode=37030675); target element is 'CheckedComboBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')

就像我之前说过的,我认为这是自定义控件的数据上下文的一个问题,但我似乎无法弄清楚如何强制它使用自己的类作为数据上下文而不是数据上下文整体网格。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我有一个类似的问题,datacontext没有继承,我用这里描述的代理技术解决了我的问题http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

<强>更新

尝试在DataGridCheckedComboColumn

中添加亲戚源
<ccb:CheckedComboBox ItemsSource="{Binding Path=ComboSource, RelativeSource={RelativeSource AncestorType=ccb:DataGridCheckedComboColumn}"

由于控件中没有指定Datacontext,我猜测它将采用其父级的Datacontext。如果这不起作用,因为DataTemplates与DataGridTemplateColumn不在同一个逻辑或可视树中,那么使用代理理念,使

<DataGridTemplateColumn x:Class="DataTracker.Presentation.GridControls.Views.DataGridCheckedComboColumn"
                        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:ccb="clr-namespace:CheckedComboBoxControl;assembly=CheckedComboBox"
                        mc:Ignorable="d">
            <DataGridTemplateColumn .Resources>
                <ccb:BindingProxy x:Key="proxy" Data="{Binding RelativeSource={RelativeSource AncestorType=ccb:DataGridCheckedComboColumn}}" />
            </DataGridTemplateColumn .Resources>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ccb:CheckedComboBox ItemsSource="{Binding Path=Data.ComboSource, Source={StaticResource proxy}}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ccb:CheckedComboBox ItemsSource="{Binding Path=Data.ComboSource, Source={StaticResource proxy}}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>