1

我在 Visual Studio 2008 中使用 WPF。我有一个简单的 WPF UserControl,代码如下:

  public partial class UserControl1 : UserControl
  {
    public UserControl1()
    {
      InitializeComponent();
      Composite = new Composite();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
      //LayoutRoot is name of default Grid instance
      if (!LayoutRoot.Children.Contains(Composite))
      {
        LayoutRoot.Children.Add(Composite);
      }
    }

    public Composite Composite
    {
      get;
      set;
    }
  }

  public class Composite : ContentControl
  {
    protected override void OnRender(DrawingContext drawingContext)
    {
      drawingContext.DrawRectangle(new SolidColorBrush(Color), new Pen(Brushes.Black, 1.0), new Rect(RenderSize));
    }

    public Color Color
    {
      get;
      set;
    }
  }

然后我在 WPF 应用程序中使用这个 UserControl,页面的 XAML 如下所示:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:test="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
    Title="Window1" Height="500" Width="700" Background="AliceBlue">
  <test:UserControl1 Name="uControl1">
    <test:UserControl1.Composite>
      <test:Composite Color="Green"/>
    </test:UserControl1.Composite>
  </test:UserControl1>
</Window>

我的问题是:我必须在上面添加什么代码,以便通过将“复合颜色”更改为绿色以外的其他颜色并点击返回按钮,UserControl 会自动刷新?我正在寻找的行为是当您将 Window1 的背景更改为 AliceBlue 以外的颜色并点击返回时会发生什么。

当我运行代码时,可以看到正确的颜色,问题出在设计时通过 XAML 刷新。

非常感谢任何帮助我理解这里发生了什么的指针!

4

2 回答 2

9

WPF 已优化为仅在绝对必要时才重新绘制项目,因此您看到的行为部分是因为 WPF 不知道当您更改 Composite.Color 时,它需要重新绘制控件。

最重要的是,Visual Studio/Blend 设计器(或 XAML 控件)将无法注意到该属性已更改,因为您的控件未发出该属性已更改的信号;如果没有该通知,WPF 不知道该属性已更改(这样可以避免它一直检查是否有更改)。

虽然您可以实现 INotifyPropertyChanged 并修复第二个问题,但由于您是从 ContentControl 继承(在继承层次结构中,它实现了 INotifyPropertyChanged),您可以使用 DependencyProperty 并修复这两个问题 - 并获得更好的 WPF 绑定支持,以开机!

// DependencyProperty backing store for Color.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColorProperty =
    DependencyProperty.Register("Color", typeof(Color), typeof(Composite), 
    new FrameworkPropertyMetadata(new Color(), FrameworkPropertyMetadataOptions.AffectsRender));

public Color Color
{
    get { return (Color)GetValue(ColorProperty); }
    set { SetValue(ColorProperty, value); }
}

通过设置FrameworkPropertyMetadataOptions.AffectsRender,WPF 知道当此属性更改时,需要再次执行此项的渲染传递,并将重新渲染您的控件,调用您的 OnRender() 方法并显示新颜色。而且,作为一个 DependencyProperty,它会自动生成正确的 PropertyChanged 事件,以便任何观看您的类(如 WPF 的绑定和动画系统)的人都会在属性更改时立即收到更新通知。

于 2009-05-27T16:57:35.613 回答
0

您正在以一种非常奇怪的方式处理此问题(让人想起 MFC 控件);花一些时间阅读 WPF Unleashed 的前半部分(http://www.amazon.com/Windows-Presentation-Foundation-Unleashed-WPF/dp/0672328917/ref=sr_1_1?ie=UTF8&s=books&qid=1243491021&sr =8-1 ),读起来很愉快,一切都会变得更有意义。

于 2009-05-28T06:11:52.353 回答