[英]WPF UserControl property change not updating
我有一个添加到主应用程序的UserControl。 该UserControl包含一个UIElement按钮
UserControl包含一个DispatchTimer,并且基于某些int值每2秒确定按钮图像将是什么。
在UserControl中调用的方法之一应该设置它的图像,但是控件从不显示更改为它的图像。
public void SetNormal()
{
btnFlashAlert.Content = new BitmapImage(new Uri("Images/FlashButton.png", UriKind.RelativeOrAbsolute));
}
在主应用程序上获得控件更新外观时,我缺少什么吗?
当我查看.Content包含的内容时,它是正确的。 用户界面不反映更改。
XAML
<UserControl x:Class="SC.FlashSystem.MainButton"
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" Height="53" Width="164">
<Button x:Name="btnFlashAlert" Background="{x:Null}" BorderBrush="{x:Null}" Cursor="Hand" Click="btnFlashAlert_Click">
<Button.Template>
<ControlTemplate>
<Image Source="Images/FlashButton.png"/>
</ControlTemplate>
</Button.Template>
</Button>
代码隐藏更新
public partial class MainButton : UserControl
{
private SupportConsoleWeb.MessageData messageCounts { get; set; }
private readonly DispatcherTimer flashButtonChangeTimer = new DispatcherTimer();
private BitmapImage NormalImage { get; set; }
private BitmapImage CriticalImage { get; set; }
private BitmapImage AlertImage { get; set; }
private BitmapImage InfoImage { get; set; }
public MainButton()
{
InitializeComponent();
messageCounts = new SupportConsoleWeb.MessageData();
messageCounts.CriticalCount = 0;
messageCounts.AlertCount = 0;
messageCounts.InfoCount = 0;
NormalImage = new BitmapImage(new Uri("Images/FlashButton.png", UriKind.RelativeOrAbsolute));
CriticalImage = new BitmapImage(new Uri("Images/FlashButtonRed.png", UriKind.RelativeOrAbsolute));
AlertImage = new BitmapImage(new Uri("Images/FlashButtonOrange.png", UriKind.RelativeOrAbsolute));
InfoImage = new BitmapImage(new Uri("Images/FlashButtonGreen.png", UriKind.RelativeOrAbsolute));
flashButtonChangeTimer.Interval = TimeSpan.FromSeconds(2);
flashButtonChangeTimer.Tick += flashButtonChangeTimer_Tick;
flashButtonChangeTimer.Start();
}
void flashButtonChangeTimer_Tick(object sender, EventArgs e)
{
btnFlashAlert.Dispatcher.BeginInvoke(new Action(() =>
{
if (btnFlashAlert.Content == null)
{
SetNormal();
}
else if (messageCounts.CriticalCount > 0 && btnFlashAlert.Content.Equals(CriticalImage))
{
SetNormal();
}
else if (messageCounts.AlertCount > 0 && btnFlashAlert.Content.Equals(AlertImage))
{
SetNormal();
}
else if (messageCounts.InfoCount > 0 && btnFlashAlert.Content.Equals(InfoImage))
{
SetNormal();
}
else if (messageCounts.CriticalCount > 0)
{
SetCritical();
}
else if (messageCounts.AlertCount > 0)
{
SetAlert();
}
else if (messageCounts.InfoCount > 0)
{
SetInfo();
}
}));
}
public void UpdateMessageCounts(SupportConsoleWeb.MessageData messageCounts)
{
this.messageCounts = messageCounts;
}
private void btnFlashAlert_Click(object sender, RoutedEventArgs e)
{
MainWindow window = new MainWindow();
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
window.ShowDialog();
}
public void SetMessageCount(int criticalCount, int alertCount, int infoCount)
{
messageCounts.CriticalCount = criticalCount;
messageCounts.AlertCount = alertCount;
messageCounts.InfoCount = infoCount;
}
private void SetNormal()
{
btnFlashAlert.Content = NormalImage;
}
private void SetCritical()
{
btnFlashAlert.Content = CriticalImage;
}
private void SetAlert()
{
btnFlashAlert.Content = AlertImage;
}
private void SetInfo()
{
btnFlashAlert.Content = InfoImage;
}
}
将您的XAML更改为此
<Image Source="{Binding TheImage}"/>
添加通知属性已更改
public partial class MainButton : UserControl, INotifyPropertyChanged
创建OnPropertyChanged事件
void OnPropertyChanged(String prop)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
创建一个位图道具并通知道具更改事件
private BitmapImage _TheImage;
public BitmapImage TheImage
{
get { return _TheImage; }
set { _TheImage = value; OnPropertyChanged("TheImage"); }
}
在您的初始值设定项中
public MainButton()
{
this.DataContext = this;
InitializeComponent();
TheImage = new BitmapImage();
现在在您的设置方法中调用
TheImage = //Your Bitmap Goes here
我知道这似乎有些过分,但从长远来看,您会发现它是一个更干净的实现。
我认为这是一个问题,当不满足任何条件时,图片选择逻辑就没有默认图片...
话虽如此, 恕我直言 ,通过预加载所有图像并将其可见性初始设置为隐藏,可以更好地表达图片逻辑。 然后将每个图像的可见性绑定到VM上的特定标志布尔值。 计时器事件可以简单地打开或关闭布尔值,而布尔值最终将根据需要显示或隐藏图像。
这样就消除了由于加载和显示图像而导致的任何延迟,因为它们将被预加载; 它还将解决由于加载/卸载图像而导致将来可能出现的任何内存问题。
下面的示例包含一个带有两个图像的按钮。 两个图像的可见性都绑定到VM上的布尔值。 虚拟机有一个布尔值,映像可以工作;一个计时器,每两秒钟切换一次图像,以更改其状态。
Xaml:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
<Button x:Name="bStatus" Width="48" Height="48">
<StackPanel Orientation="Vertical">
<Image Source="Images\Copy-icon.png" Visibility="{Binding IsCopyOn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<Image Source="Images\Recycle-icon.png"
Visibility="{Binding IsRecycleOn,
Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</Button>
虚拟机
public class MainVM : INotifyPropertyChanged
{
private bool _bSwitch;
private readonly DispatcherTimer flashButtonChangeTimer = new DispatcherTimer();
public bool IsRecycleOn
{
get { return _bSwitch; }
}
public bool IsCopyOn
{
get { return !_bSwitch; }
}
public MainVM()
{
flashButtonChangeTimer.Interval = TimeSpan.FromSeconds(2);
flashButtonChangeTimer.Tick += (sender, args) =>
{
_bSwitch = ! _bSwitch;
OnPropertyChanged("IsCopyOn");
OnPropertyChanged("IsRecycleOn");
};
flashButtonChangeTimer.Start();
}
/// <summary>Event raised when a property changes.</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Raises the PropertyChanged event.</summary>
/// <param name="propertyName">The name of the property that has changed.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.