0

我定义了两个UserControls

  • 绘图:包含一个CustomCanvas派生自Canvas.
  • 控件:包含一个Button和用于改变GlobalThickness属性MyViewModel.cs

CustomCanvas有一个名为 的自定义依赖属性ThicknessGlobalThickness这在 XAML 中是绑定的。

我还重写了绘制 a的OnRender方法,使用它的厚度设置为.CustomCanvasRectanglePenThickness

当我单击 时ButtonGlobalThickness更改和Thickness绑定到它的 也发生了变化。但我没有得到Rectangle一个新的Thickness

到目前为止,这是我整理的所有代码。

<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));
        }
    }
}
4

2 回答 2

1

这种替代方案可能更有效。每次更改 Pen Thickness 时都不会频繁调用OnRender和重新渲染所有内容,它只是更改仅进行一次的现有渲染的 Pen's Thickness。视觉输出将由 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;
    }
}
于 2014-08-13T22:04:44.550 回答
1

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); }
}
于 2014-08-13T21:33:21.010 回答