如何为 <If> WPF XAML 编写用户控件



我已经在编写一个用户控件方面取得了一些进展,它不仅可以隐藏内容,而且可以在不满足某些条件时完全删除

。几个用例:

<mynamespace:If Condition="{Binding PerformingWork}">
    <LoadingThrobber />
</mynamespace:If>
<mynamespace:If Condition="{Binding HasResults}">
    <ItemsControl ...>
        ...
    </ItemsControl>
</mynamespace:If>

<mynamespace:If Condition="{Binding UserHasMorePermissions}">
    ...
</mynamespace:If>

等。

我的解决方案似乎有效,但有一个严重的缺点:If "块"在被删除之前仍然加载一次(通过在某些子控件的构造函数中放置MessageBox.Show(…)很容易证明)。我想阻止内容运行,以防它试图做一些繁重的工作,或操作尚不存在的数据等。

这是我目前想到的:

    public partial class If : UserControl
    {
        private object ConditionalContent { get; set; }
        public If()
        {
            InitializeComponent();
            Loaded += OnLoad;
        }
        private void OnLoad(object sender, RoutedEventArgs e)
        {
            ConditionalContent = Content;
            Loaded -= OnLoad;
            OnConditionChanged();
        }
        private void OnConditionChanged()
        {
            Content = Condition ? ConditionalContent : null;
        }
        // === component properties
        // omg, WPF
        public bool Condition
        {
            get { return (bool)GetValue(ConditionProperty); }
            set { SetValue(ConditionProperty, value); }
        }
        public static readonly DependencyProperty ConditionProperty = DependencyProperty.Register("Condition", typeof(bool), typeof(If), new PropertyMetadata(OnConditionChangedCallback));
        
        private static void OnConditionChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender is If s)
            {
                s.OnConditionChanged();
            }
        }
    }

XAML基本为空;我把它包括进来只是为了以防这里有重要的东西:

<UserControl x:Class="XamlExtensions.If"
             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:XamlExtensions"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
</UserControl>

当然,如果有另一种方法来实现同样的目标,那就太好了。

我会使用自定义控件而不是用户控件,并使默认子属性为自定义DependencyProperty并手动添加到控件的内容

[ContentProperty("ConditionalContent")]
public partial class If : ContentControl
{
    public If()
    {
        Loaded += OnLoad;
    }
    private void OnLoad(object sender, RoutedEventArgs e)
    {
        update();
    }
    private void update()
    {
        Content = Condition ? ConditionalContent : null;
    }
    // === component properties
    // omg, WPF
    public bool Condition
    {
        get { return (bool)GetValue(ConditionProperty); }
        set { SetValue(ConditionProperty, value); }
    }
    public static readonly DependencyProperty ConditionProperty = DependencyProperty.Register("Condition", typeof(bool), typeof(If), new PropertyMetadata(OnConditionChangedCallback));
    private static void OnConditionChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (sender is If s)
        {
            s.update();
        }
    }

    public object ConditionalContent
    {
        get { return (object)GetValue(ConditionalContentProperty); }
        set { SetValue(ConditionalContentProperty, value); }
    }
    public static readonly DependencyProperty ConditionalContentProperty =
        DependencyProperty.Register("ConditionalContent", typeof(object), typeof(If), new PropertyMetadata(null,OnConditionChangedCallback));

}

它是这样工作的

<local:If Condition="{Binding}">
    sdgdfhsh <!-- or anything else! -->
</local:If>

相关内容

  • 没有找到相关文章

最新更新