【问题标题】:WPF - Dependency Property InitialisationWPF - 依赖属性初始化
【发布时间】:2018-02-15 11:20:39
【问题描述】:

我正在尝试实现一个将图像投影到 3D 模型上的 WPF 组件。为了使其使用起来更整洁,我尝试使用依赖属性,以便我可以通过以下方式从我的视图中绑定控件:

<viewers:MyViewer
    ProjectedImageSource="{Binding ViewModel.ProjectedSource}"
    Visibility="{Binding Path=HueMapVisible, Converter={StaticResource booleanToVisibilityConverter}}"
    />

控件如下:

<UserControl x:Class="ImageProjector.Controls.Viewers.MyViewer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
    <LayoutGrid>
        <Viewport3D Name="Viewport" Grid.ColumnSpan="7" Grid.RowSpan="7" />
    </LayoutGrid>
</UserControl>

代码隐藏:

public interface IMyViewer { }

public partial class MyViewer : UserControl, IMyViewer
{
    private IImageModel3D imageModel3D;

    public MyViewer() : this(Ninjector.Get<IImageModel3D>()){ }

    public MyViewer(IImageModel3D imageModel3D)
    {
        this.InitializeComponent();

        this.ProjectedImageSource.Changed += ProjectedImageSource_Changed;
    }

    private void ProjectedImageSource_Changed(object sender, EventArgs e)
    {
        imageModel3D.SetImage((BitmapImage)sender);
    }

    public static readonly DependencyProperty ProjectedImageSourceProperty = DependencyProperty.Register(
                                                                    "ProjectedImageSource",
                                                                    typeof(BitmapSource),
                                                                    typeof(MyViewer));

    public BitmapSource ProjectedImageSource
    {
        get => (BitmapSource)this.GetValue(ProjectedImageSourceProperty);
        set => this.SetValue(ProjectedImageSourceProperty, value);
    }
}

我遇到的问题是,在构造函数中调用 ProjectedImageSource 时为 null(我也在 Loaded 回调中尝试过),因此我无法设置 Changed 事件处理程序。

我知道有一个 ValidateValue 回调,但这需要是一个静态静态,因此在这种情况下不起作用。

我可以使用一些技巧来使此功能正常工作,还是尝试这样做存在根本缺陷?

【问题讨论】:

    标签: c# wpf dependency-properties


    【解决方案1】:

    您应该使用依赖属性元数据注册一个 PropertyChangedCallback:

    public static readonly DependencyProperty ProjectedImageSourceProperty =
        DependencyProperty.Register(
            nameof(ProjectedImageSource),
            typeof(BitmapSource),
            typeof(MyViewer),
            new PropertyMetadata(ProjectedImageSourceChanged));
    
    private static void ProjectedImageSourceChanged(
        DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var viewer = (MyViewer)obj;
    
        viewer.imageModel3D.SetImage(e.NewValue as BitmapImage); // may not be a BitmapImage
    }
    

    或更短:

    public static readonly DependencyProperty ProjectedImageSourceProperty =
        DependencyProperty.Register(
            nameof(ProjectedImageSource),
            typeof(BitmapSource),
            typeof(MyViewer),
            new PropertyMetadata(
                (o, e) => ((MyViewer)o).imageModel3D.SetImage(e.NewValue as BitmapImage)));
    

    请注意,您的 IImageModel3D.SetImage 方法似乎不需要 BitmapImage 参数。最好改用BitmapSource,并像这样编写您的PropertyChangedCallback:

    public static readonly DependencyProperty ProjectedImageSourceProperty =
        DependencyProperty.Register(
            nameof(ProjectedImageSource),
            typeof(BitmapSource),
            typeof(MyViewer),
            new PropertyMetadata(
                (o, e) => ((MyViewer)o).imageModel3D.SetImage((BitmapSource)e.NewValue)));
    

    如果 SetImage 确实需要 BitmapImage,则应更改依赖属性的类型。

    【讨论】:

    • 非常感谢,第二种形式正是我所需要的
    猜你喜欢
    • 2021-10-09
    • 2012-07-25
    • 1970-01-01
    • 2017-11-29
    • 2014-05-23
    相关资源
    最近更新 更多