如何写一个<If>WPF XAML 的用户控件 [英] how to write an <If> user control for WPF XAML
问题描述
我在编写用户控件方面取得了一些进展,该控件不仅隐藏内容,而且在不满足某些条件时将其完全删除.
I've made some progress writing a user control which doesn't just hide content, but completely removes it, if some condition isn't met.
几个示例用例:
<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(...) 很容易证明).我想完全阻止内容运行,以防它尝试做一些繁重的工作,或者对尚不存在的数据进行操作等.
my solution APPEARS to work, but has a serious downside: the contents of the If "block" are still loaded once, before being removed (easily proved by putting a MessageBox.Show(...) in some child control's constructor). I want to prevent the content from running AT ALL, in case it's trying to do some heavy work, or operate on data that doesn't yet exist, etc.
这是我目前想到的:
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 基本是空的;我将其包括在内,以防万一这里有重要的事情:
the XAML is basically empty; I'm including it juuuust in case there's something important here:
<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>
当然,如果有另一种方式来实现同样的目标,那就太好了.
of course, if there's another way to accomplish the same goal, that'd be great.
推荐答案
我会使用 Custom Control 而不是 User Control 并使默认子项成为自定义 DependencyProperty并手动添加到控件的内容
I would use a Custom Control and not a User Control and make the default child a custom DependencyProperty and add to the control's content manually
[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>
这篇关于如何写一个<If>WPF XAML 的用户控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!