【发布时间】:2021-07-23 13:11:29
【问题描述】:
我在编写用户控件方面取得了一些进展,该控件不仅隐藏内容,而且在不满足某些条件时将其完全删除。
几个示例用例:
<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>
当然,如果有其他方法可以实现相同的目标,那就太好了。
【问题讨论】:
-
标记扩展似乎很合适。或者您可以将控件子类化并操作其控件模板,当条件评估为
false时将其设为null。 -
显示/隐藏某些内容的更通用方法是使用data trigger 操作可见性或控制模板。您也可以使用converter 将条件绑定到
Visibility。有很多方法。 -
这不是一个好主意。您将使用冗余的用户控件使您的可视化树膨胀。这会降低应用程序的性能,尤其是在渲染方面。您应该使用triggers、样式和模板。绑定转换器也是一个选项(如前所述):How to: Convert Bound Data。您只需使用触发器切换
UIElement.Visibility。 -
你能不能这样设计屏幕,在那里你可以利用内容控制或数据模板?