【问题标题】:Using attached properties in WPF在 WPF 中使用附加属性
【发布时间】:2016-03-02 00:13:56
【问题描述】:

我正在尝试在 WPF 中创建一个只读附加属性,该属性将计算控件的总 Visual Child 计数。这样做的好处对我来说并不重要,它能够正确使用附加属性!

首先我已经这样声明了我的财产:

internal static readonly DependencyPropertyKey TotalChildCountPropertyKey =
        DependencyProperty.RegisterAttachedReadOnly("TotalChildCount", typeof(int), typeof(MyAttachClass), new FrameworkPropertyMetadata(0));

    public static readonly DependencyProperty TotalChildCountProperty = TotalChildCountPropertyKey.DependencyProperty;


    public static int GetTotalChildCount(DependencyObject obj)
    {
        return (int)obj.GetValue(TotalChildCountProperty);
    }

    public static void SetTotalChildCount(DependencyObject obj, int value)
    {
        obj.SetValue(TotalChildCountPropertyKey, value);
    }

我也有一个递归方法声明 else where 像这样:

public static class Recursive
{
    public static IEnumerable<DependencyObject> GetAllChildren(DependencyObject obj)
    {
        List<DependencyObject> col = new List<DependencyObject>();
        GetAllChildrenImp(obj, col);
        return col;

    }

    private static void GetAllChildrenImp(DependencyObject current,     List<DependencyObject> col)
    {
        if (current != null)
        {
            col.Add(current);

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(current); i++ )
            {
                GetAllChildrenImp(VisualTreeHelper.GetChild(current, i), col);
            }
        }   
    }
}

现在我希望使用此方法为 GetTotalChildCount 属性分配一个值,但我想不出最好的方法。我可以为依赖属性更改添加一个事件处理程序,但这永远不会触发,因为我只会从 xaml 中的值读取。

这是我在 xaml 中的使用方式:

<TextBox DataContext="{RelativeSource Self}" Text="{Binding local:MyAttachClass.TotalChildCount}"></TextBox>

所以总结一下。我希望设置一个 DependencyObjects TotalChildCount 附加属性,然后能够在 xaml 中绑定到它。就目前而言,这不起作用,GetTotalChildCount 甚至没有受到打击。

哦,这是我的第一个问题,希望我足够清楚

【问题讨论】:

  • 是否需要给 TextBox 添加子元素?我认为只有 Grid/StackPanel/DockPanel 等容器控件才允许有子控件。
  • 我不需要添加孩子。 GetAllChildren 方法将返回构成 TextBox 的所有依赖对象,例如边框等
  • GetTotalChildCount() 应至少调用一次。但是,如果您不调用SetTotalChildCount(),则可能不会针对给定的绑定再次调用它。不幸的是,没有一个好的minimal reproducible example 可以可靠地重现您的问题,很难确切地知道您要做什么,更不用说如何修复代码了。

标签: c# wpf xaml binding


【解决方案1】:

你可以这样试试

附加属性

public class MyAttachClass
{
    public static readonly DependencyProperty TotalChildCountProperty = DependencyProperty.RegisterAttached("TotalChildCount", typeof(int), typeof(MyAttachClass), 
    new PropertyMetadata(-1, OnTotalChildCountChanged));

    public static int GetTotalChildCount(DependencyObject obj)
    {
        return (int)obj.GetValue(TotalChildCountProperty);
    }

    public static void SetTotalChildCount(DependencyObject obj, int value)
    {
        obj.SetValue(TotalChildCountProperty, value);
    }

    public static void OnTotalChildCountChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        TextBox txt = sender as TextBox;
        if (txt != null)
        {
            var children = Recursive.GetAllChildren(txt);
            txt.Text = children.Count().ToString();
        }
    }
}

而 xaml 为

<TextBox local:MyAttachClass.TotalChildCount="0" ></TextBox>

希望对你有帮助!

【讨论】:

  • OP 正在实现一个只读属性。以上不是只读的(更糟糕的是,通过在附加的属性控件本身中硬编码客户端元素的属性更改行为,建议完全与客户端元素过度耦合)。