如何在ImageSource
的自定义wpf控件上实现DependencyProperty
?如何在ImageSource的自定义wpf控件上实现DependencyProperty?
我创建了一个自定义控件(按钮),其中包括显示图像。我希望能够从控件的外部为图像设置ImageSource,所以我实现了一个DependencyProperty。每当我尝试更改ImageSource时,我都会收到一个SystemInvalidOperationException
:“调用线程无法访问此对象,因为不同的线程拥有它。”
好吧,所以主线程无法访问图像控件,所以我需要使用Dispatcher - 但是在哪里以及如何?显然,抛出异常在设定器,执行SetValue(ImageProperty, value);
tv_CallStart.xaml:
<Button x:Class="EHS_TAPI_Client.Controls.tv_CallStart" x:Name="CallButton"
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="24" d:DesignWidth="24" Padding="0" BorderThickness="0"
Background="#00000000" BorderBrush="#FF2467FF" UseLayoutRounding="True">
<Image x:Name="myImage"
Source="{Binding ElementName=CallButton, Path=CallImage}" />
</Button>
tv_CallStart.xaml.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace EHS_TAPI_Client.Controls
{
public partial class InitiateCallButton : Button
{
public ImageSource CallImage
{
get { return (ImageSource)GetValue(CallImageProperty); }
set { SetValue(CallImageProperty, value); }
}
public static readonly DependencyProperty CallImageProperty =
DependencyProperty.Register("CallImage", typeof(ImageSource), typeof(InitiateCallButton), new UIPropertyMetadata(null));
public InitiateCallButton()
{
InitializeComponent();
}
}
}
设定从UI-的代码隐藏图像线程:
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("pack://application:,,,/EHS-TAPI-Client;component/Images/call-start.png");
bi.EndInit();
bi.Freeze();
CallButton.CallImage = bi;
和MainWindow.xaml其中控件初始化lised:
<ctl:InitiateCallButton x:Name="CallButton" CallImage="/Images/call-start.png" />
改编上面的源代码,以反映我的进步..
解决方案:
上面的代码发布工作正常。最初版本的重要变化是添加了UI线程中的Freeze()方法(请参阅接受的答案)。 我的项目中的实际问题不是按钮不是在UI线程中被初始化,但是新图像是从另一个线程设置的。该图像设置在一个事件处理程序中,该程序本身由另一个线程触发。我使用Dispatcher
解决了这个问题:
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri("pack://application:,,,/EHS-TAPI-Client;component/Images/call-start.png");
bi.EndInit();
bi.Freeze();
if (!Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate()
{
CallButton.CallImage = bi;
});
}
else
{
CallButton.CallImage = bi;
}
wth class names? –
你是对的,我很惭愧。特别是我倾向于遵循最佳实践和命名惯例。这些课程是前一段时间创建的,我甚至不记得为什么我这次没有正确地命名它们。这实际上使事情更糟糕o。O –
至少你似乎没有混合德语,它可能更糟糕:P –