【问题标题】:How to properly expose properties of internal controls?如何正确暴露内部控制的属性?
【发布时间】:2018-05-15 14:33:50
【问题描述】:

我有一个名为 CustomTreeView 的自定义控件,其中包含一个 TreeView。我想向自定义控件的用户公开TreeViewSelectedItem 属性。

为此,我尝试向自定义控件添加一个新的依赖属性并将该属性绑定到TreeViewSelectedItem 属性。

不幸的是,我似乎弄错了。你能看一下吗?

TreeView.xaml

<UserControl x:Class="Fis.UI.Windows.BacNet.Views.RestructuredView.View.Controls.CustomTreeView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Selected="{Binding ElementName=treeView, Path=SelectedItem}">
   <TreeView x:Name="treeView"/>
</UserControl>

TreeView.xaml.cs

public partial class CustomTreeView : UserControl
    {
        public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
                                                                                             "Selected", typeof(Node),
                                                                                             typeof(TreeView)
                                                                                             );
        public Node Selected
        {
            get { return (Node)GetValue(IsSelectedProperty); }
            set { SetValue(IsSelectedProperty, value); }
        }

        public TreeView()
        {
            InitializeComponent();
        }
    }

谢谢!

【问题讨论】:

  • 您添加的 Selected 属性是 TreeView 的一部分,而不是 UserControl。所以你只能这样做: 。您想通过 UserControl 类访问 Selected 属性吗?
  • 我希望Fis.UI.Windows.BacNet.Views.RestructuredView.View.Controls.TreeView 类的用户绑定到嵌套在此类中的 TreeView 的 SelectedItem。为此,我需要公开嵌套 TreeView 的 SelectedItem 属性。

标签: c# wpf


【解决方案1】:

您的部分解决方案是in this answer here。这是一个带有死链接的仅链接答案(或者是 - 我只是改进了它),但它确实提到了关键点。

您无法绑定TreeView.SelectedItem。您的依赖项属性定义以多种方式被破坏,应根据标准 WPF 实践将其命名为 SelectedItem。这是后面的用户控件代码,它定义了依赖属性以及事件处理程序作为绑定的替代品。

public partial class CustomTreeView : UserControl
{
    public CustomTreeView()
    {
        InitializeComponent();
    }

    #region SelectedItem Property
    public Node SelectedItem
    {
        get { return (Node)GetValue(SelectedProperty); }
        set { SetValue(SelectedProperty, value); }
    }

    public static readonly DependencyProperty SelectedProperty =
        DependencyProperty.Register(nameof(SelectedItem), typeof(Node), typeof(CustomTreeView),
            new FrameworkPropertyMetadata(null,
                                          FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                          Selected_PropertyChanged)
            { DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });

    protected static void Selected_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as CustomTreeView).OnSelectedChanged(e.OldValue);
    }

    private void OnSelectedChanged(object oldValue)
    {
        if (SelectedItem != treeView.SelectedItem)
        {
            var tvi = treeView.ItemContainerGenerator.ContainerFromItem(SelectedItem) as TreeViewItem;

            if (tvi != null)
            {
                tvi.IsSelected = true;
            }
        }
    }
    #endregion SelectedItem Property

    private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (SelectedItem != e.NewValue)
        {
            SelectedItem = e.NewValue as Node;
        }
    }
}

这是 UserControl XAML 中的 TreeView。我忽略了 ItemsSource 和 ItemTemplate 无关紧要。

<TreeView
    x:Name="treeView"
    SelectedItemChanged="treeView_SelectedItemChanged"
    />

这是我用来测试它的 MainWindow.xaml 中的 sn-p:

<StackPanel>
    <local:CustomTreeView x:Name="treeControl" />
    <Label 
        Content="{Binding SelectedItem.Text, ElementName=treeControl}"
        />
</StackPanel>

我的 Node 类有一个 Text 属性,我通过 DataContext 填充树,以节省必须为项目设置另一个依赖项属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 2014-09-19
    相关资源
    最近更新 更多