我正在尝试实现将图像投射到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>
codebehind:
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是无效的(我也在已加载的回调中尝试过(,所以我无法设置更改的事件处理程序。
我知道有一个validateValue回调,但这必须是静态静态,因此在这种情况下不起作用。
我可以用一些技巧来使此功能起作用,还是从根本上有缺陷来尝试?
您应该在依赖属性元数据中注册一个属性ChangedCallback:
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
,然后以这样的方式编写您的属性ChangedCallback:
public static readonly DependencyProperty ProjectedImageSourceProperty =
DependencyProperty.Register(
nameof(ProjectedImageSource),
typeof(BitmapSource),
typeof(MyViewer),
new PropertyMetadata(
(o, e) => ((MyViewer)o).imageModel3D.SetImage((BitmapSource)e.NewValue)));
如果设定确实需要一个位图像,则应更改依赖项属性的类型。