【问题标题】:UserControl with Dependancy Properties to replace repetative set of similiar controls具有依赖属性的 UserControl 以替换重复的类似控件集
【发布时间】:2011-07-27 10:41:47
【问题描述】:

抱歉,问题标题很糟糕,我不知道如何表达,欢迎评论。

我正在使用 MVVM 模式开发 WPF 桌面应用程序。我的 ViewModel 上有大量文本字段,我想使用以下模式显示所有这些字段(非常简化):

<StackPanel Orientation="Vertical">
    <StackPanel.Style>
        <Style TargetType="{x:Type StackPanel}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=SomePredicate}" Value="False">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </StackPanel.Style>

    <Label Content="SomeHeader:"/>

    <TextBlock Text="{Binding Path=SomeText}" />

</StackPanel>

显示始终包括:

  • 用于确定是否应显示 StackPanel 的谓词
  • 用作标题文本的字符串。这可以在 XAML 中设置,它不必来自视图模型
  • 绑定到 ViewModel 上的 Textblock 文本字符串

我真的很想能够像这样定义这些:

<MyHeaderedTextBlockControl Text="{Binding Path=SomeText}"
                            Header="SomeHeader:"
                            Predicate="{Binding SomePredicate}"/>

这可以吗?我尝试使用 UserControl 进行操作,但不知道自己在做什么。

绑定模式保持工作对我来说很重要,即如果Text 绑定处于OneWayTwoWay 模式,则TextBlock 应该在ViewModel 上的Text 属性引发@ 时更新987654328@.

我也不喜欢为每个此类文本属性使用 View 和 ViewModel 执行此操作的想法,因为我必须创建这些 ViewModel 并将它们连接起来以进行更新等。我想要一个可以在View,理想情况下 ViewModel 甚至不应该知道它。

【问题讨论】:

  • 我不明白这一行:“我想要一个可以在 View 中实现的解决方案,理想情况下 ViewModel 甚至不应该知道它。”无论如何,您都需要在 viewmodel 中创建 Text、Header、Predicate 属性。
  • @anivas 是的,当然,但这些属性已经存在。 ViewModel 为谓词公开一个布尔属性,为文本公开一个字符串属性。每次构建此类构造时,我将在视图的 XAML 中定义的标头。
  • 你可以用这些属性创建一个用户控件作为控件的依赖属性,如果你有很多这样的文本框(我希望你有一个文本、标题和布尔值的集合)你可以创建一个项目控件数据模板。你被困在哪里了?

标签: wpf data-binding mvvm user-controls datatemplate


【解决方案1】:

使用 UserControls,您可以在代码中定义依赖属性并通过绑定将它们转发到“模板”,例如:

<UserControl x:Class="Test.UserControls.HeaderedTextBlock"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Name="control">
    <StackPanel Orientation="Vertical">
        <StackPanel.Style>
            <Style TargetType="{x:Type StackPanel}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Predicate, ElementName=control}" Value="False">
                        <Setter Property="Visibility" Value="Collapsed" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Style>
        <Label Content="{Binding Header, ElementName=control}" />
        <TextBlock Text="{Binding Text, ElementName=control}" />
    </StackPanel>
</UserControl>
namespace Test.UserControls
{
    public partial class HeaderedTextBlock : UserControl
    {

        public static readonly DependencyProperty HeaderProperty =
            DependencyProperty.Register("Header", typeof(string), typeof(HeaderedTextBlock), new UIPropertyMetadata(null));
        public string Header
        {
            get { return (string)GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }

        public static readonly DependencyProperty PredicateProperty =
            DependencyProperty.Register("Predicate", typeof(bool), typeof(HeaderedTextBlock), new UIPropertyMetadata(false));
        public bool Predicate
        {
            get { return (bool)GetValue(PredicateProperty); }
            set { SetValue(PredicateProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(HeaderedTextBlock), new UIPropertyMetadata(null));
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public HeaderedTextBlock()
        {
            InitializeComponent();
        }
    }
}

这样的东西对你有用吗?

【讨论】:

  • 这绝对是完美的,非常棒!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
  • 1970-01-01
  • 2013-01-14
  • 2017-12-24
相关资源
最近更新 更多