OnRender 方法在 WPF 中不显示粗细设置为依赖项属性的矩形



我定义了两个UserControls:

  • 绘图:包含CustomCanvas,源自Canvas
  • 控件:包含Button,用于更改MyViewModel.cs
  • 中的GlobalThickness属性。

CustomCanvas有一个名为Thickness的自定义依赖属性。这在XAML中被绑定到GlobalThickness

我还覆盖了CustomCanvas中的OnRender方法,使用Pen绘制Rectangle,其厚度设置为Thickness

当我点击Button时,GlobalThickness改变了,绑定到它的Thickness也改变了。但是我没有得到一个新的ThicknessRectangle

这是我目前整理的所有代码。

<Window x:Class="WpfApplication23.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:WpfApplication23">
    <Window.DataContext>
        <local:MyViewModel></local:MyViewModel>
    </Window.DataContext>
    <StackPanel>
        <local:Drawing/>
        <local:Control/>
    </StackPanel>
</Window>
<UserControl x:Class="WpfApplication23.Drawing"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:wpfApplication23="clr-namespace:WpfApplication23">
    <Grid>
        <wpfApplication23:CustomCanvas Thickness="{Binding GlobalThickness}"
                                       Height="100" 
                                       Width="100" 
                                       Background="Blue"/>
    </Grid>
</UserControl>
<UserControl x:Class="WpfApplication23.Control"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Button Content="Change Thickness" 
                Width="200" 
                Height="30"
                Click="ButtonBase_OnClick"/>
    </StackPanel>
</UserControl>

public partial class Control
{
    public Control()
    {
        InitializeComponent();
    }
    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        var vm = (MyViewModel)DataContext;
        vm.GlobalThickness = 10;
    }
}

public class CustomCanvas : Canvas
{
    public int Thickness
    {
        private get { return (int)GetValue(ThicknessProperty); }
        set
        {
            SetValue(ThicknessProperty, value); 
            InvalidateVisual();
        }
    }
    public static readonly DependencyProperty ThicknessProperty =
        DependencyProperty.Register("Thickness", typeof(int), typeof(CustomCanvas), new PropertyMetadata(0));
    protected override void OnRender(DrawingContext dc)
    {
        var myPen = new Pen(Brushes.Red, Thickness);
        var myRect = new Rect(0, 0, 400, 400);
        dc.DrawRectangle(null, myPen, myRect);
    }
}

public class MyViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private double _globalThickness = 1;
    public double GlobalThickness
    {
        get { return _globalThickness; }
        set
        {
            _globalThickness = value;
            RaisePropertyChanged("GlobalThickness");
        }
    }
    private void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

这种替代方法可能更有效。而不是频繁调用OnRender和重新渲染每一次钢笔的厚度改变,它只是改变钢笔的厚度,现有的渲染只做一次。视觉输出将由WPF自动更新。

public class CustomCanvas : Canvas
{
    private readonly Pen pen = new Pen(Brushes.Red, 0d);
    public static readonly DependencyProperty ThicknessProperty =
        DependencyProperty.Register(
            "Thickness", typeof(double), typeof(CustomCanvas),
            new PropertyMetadata(ThicknessPropertyChanged));
    public double Thickness
    {
        get { return (double)GetValue(ThicknessProperty); }
        set { SetValue(ThicknessProperty, value); }
    }
    protected override void OnRender(DrawingContext drawingContext)
    {
        var myRect = ...
        drawingContext.DrawRectangle(null, pen, myRect);
    }
    private static void ThicknessPropertyChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        ((CustomCanvas)obj).pen.Thickness = (double)e.NewValue;
    }
}

当绑定设置属性时,不会调用属性setter和InvalidateVisual();。原因在XAML加载和依赖属性中有解释。

你可以用你的依赖属性注册属性元数据,当属性值改变时强制重新呈现:

public static readonly DependencyProperty ThicknessProperty =
    DependencyProperty.Register(
        "Thickness", typeof(int), typeof(CustomCanvas),
        new FrameworkPropertyMetadata(
            default(int), FrameworkPropertyMetadataOptions.AffectsRender));

为什么Thickness是整数?也可以是double:

public static readonly DependencyProperty ThicknessProperty =
    DependencyProperty.Register(
        "Thickness", typeof(double), typeof(CustomCanvas),
        new FrameworkPropertyMetadata(
            default(double), FrameworkPropertyMetadataOptions.AffectsRender));
public double Thickness
{
    get { return (double)GetValue(ThicknessProperty); }
    set { SetValue(ThicknessProperty, value); }
}

相关内容

  • 没有找到相关文章

最新更新