0

私は2つを定義しましたUserControls:

  • 図面:CustomCanvasから派生した が含まれていますCanvas
  • コントロール: が含まれており、プロパティButtonを変更するために使用されますGlobalThicknessMyViewModel.cs

CustomCanvasは、 という名前のカスタム依存関係プロパティがありThicknessます。GlobalThicknessこれはXAML にバインドされています。

また、厚さが に設定されているを使用して を描画するOnRenderメソッドをオーバーライドしました。CustomCanvasRectanglePenThickness

をクリックするButtonと、GlobalThickness変更と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

プロパティ セッター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 に答える
1

この代替手段は、より効率的である可能性があります。ペンの太さが変更されるたびにすべてを頻繁に呼び出し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;
    }
}
于 2014-08-13T22:04:44.550 に答える