视图模型子属性上的WPF自定义控件重新渲染更改

时间:2016-11-30 05:09:41

标签: c# .net wpf data-binding custom-controls

WPF自定义控件跟踪视图模型子属性是否可以更改为自动重新呈现?

假设我有一个包含两个属性的模型:

public class FullName : ViewModel
{
    string _first;
    string _last;

    public string First
    {
        get { return _first; }
        set
        {
            _first = value;
            RaisePropertyChanged();
        }
    }

    public string Last
    {
        get { return _last; }
        set
        {
            _last = value;
            RaisePropertyChanged();
        }
    }
}

ViewModel的位置:

public abstract class ViewModel : INotifyPropertyChanged
{
    protected void RaisePropertyChanged([CallerMemberName] string propertyName = null) =>
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) =>
        PropertyChanged?.Invoke(this, e);

    public event PropertyChangedEventHandler PropertyChanged;
}

我希望在WPF自定义控件(AffectsRender,没有SubPropertiesDoNotAffectRender)上有一个依赖属性来引用模型,以便控件在First和{{自动重新呈现1}}属性更改:

Last

以下是测试它的代码段:

public class Tag : Control
{
    public static readonly DependencyProperty FullNameProperty =
        DependencyProperty.Register("FullName", typeof(FullName), typeof(Tag),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));

    public FullName FullName
    {
        get { return (FullName)GetValue(FullNameProperty); }
        set { SetValue(FullNameProperty, value); }
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        if (FullName == null)
            return;

        FontFamily courier = new FontFamily("Courier New");
        Typeface courierTypeface = new Typeface(courier, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
        FormattedText ft2 = new FormattedText(FullName.First + " " + FullName.Last,
                                             CultureInfo.CurrentCulture,
                                             FlowDirection.LeftToRight,
                                             courierTypeface,
                                             14.0,
                                             Brushes.Black);

        drawingContext.DrawText(ft2, new Point());
    }
}

不幸的是,它不起作用 - 更改不会传播到自定义控件。可以有效地完成吗?这个<Window x:Class="WpfApplication3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication3" mc:Ignorable="d" Title="MainWindow" Height="139.9" Width="249.514"> <StackPanel> <StackPanel.DataContext> <local:FullName> <local:FullName.First>John</local:FullName.First> <local:FullName.Last>Doe</local:FullName.Last> </local:FullName> </StackPanel.DataContext> <local:Tag FullName="{Binding}" Height="20"/> <TextBox Text="{Binding First, UpdateSourceTrigger=PropertyChanged}"/> <TextBox Text="{Binding Last, UpdateSourceTrigger=PropertyChanged}"/> </StackPanel> </Window> 到底是什么意思?

1 个答案:

答案 0 :(得分:1)

为此,FullName课程必须是FreezableFirstLast属性必须是依赖属性。

您可以查看DependencyObject的{​​{3}}:

internal void NotifySubPropertyChange(DependencyProperty dp)
{
    InvalidateSubProperty(dp);

    // if the target is a Freezable, call FireChanged to kick off
    // notifications to the Freezable's parent chain.
    Freezable freezable = this as Freezable;
    if (freezable != null)
    {
        freezable.FireChanged();
    }
}

此机制最初不用于观察绑定视图模型的子属性。通过观察FrameworkElement s`属性并触发更改其属性和子属性的适当操作,有助于简化Freezable的测量,排列和渲染。

你可以找到一篇不错的博客文章current implementation,它解释了WPF中保留的图形系统如何工作以及如何使用你感兴趣的功能。