我有一个简单的viewmodel类,它包含三个属性。
public class ColorViewModel : INotifyPropertyChanged
{
private int red;
public int Red
{
get { return red; }
set
{
if (red != value)
{
red = value;
RaisePropertyChanged("Red");
}
}
}
private int green;
public int Green
{
get { return green; }
set
{
if (green != value)
{
green = value;
RaisePropertyChanged("Green");
}
}
}
private int blue;
public int Blue
{
get { return blue; }
set
{
if (blue!= value)
{
blue = value;
RaisePropertyChanged("Blue");
}
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
现在我想将整个模型传递给给定的转换器,以便为RGB值创建颜色。
<Rectangle Grid.Row="4" Grid.Column="1" HorizontalAlignment="Center" Height="120" Width="120"
Fill="{Binding Model, Converter={StaticResource intToBrushValueConverter}}"/>
其中Model
是我ColorViewModel
的一个实例。
问题是intToBrushValueConverter
转换器只在程序启动时触发一次。换句话说,更改Model
时不会触发转换器。
然后,当ColorViewModel
的一个属性发生变化时,PropertyChanged
正在运行,initToBrushValueConverter
转换器无法正常运行。
有一种方法可以解决这个问题吗?
我在不使用MultiBinding
或CommandParameter
的情况下搜索一个解决方案。
提前致谢。
答案 0 :(得分:1)
当属性在Color属性上发生更改时,Hook属性将事件更改为父视图模型和fire属性更改事件。
public class ParentViewModel : INotifyPropertyChanged
{
private ColorViewModel color;
public ColorViewModel Color
{
get { return color; }
set
{
if (color != value)
{
if (color != null)
color.PropertyChanged -= this.ChildPropertyChanged;
color = value;
if (color != null)
color.PropertyChanged += this.ChildPropertyChanged;
RaisePropertyChanged("Color");
}
}
}
private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(Color == sender)
{
RaisePropertyChanged("Color");
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
<强>更新强>
下面的完整工作解决方案。
MainWindows.xaml.cs
using System;
using System.Windows;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Random random = new Random();
private ParentViewModel model;
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
this.model = new ParentViewModel();
this.model.Color = new ColorViewModel();
}
public ParentViewModel Model
{
get { return model; }
set
{
model = value;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.model.Color.Blue = (byte)random.Next(0, 255);
this.model.Color.Green = (byte)random.Next(0, 255);
this.model.Color.Red = (byte)random.Next(0, 255);
}
}
}
MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:IntToBrushConverter x:Key="intToBrushConverter" />
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Rectangle HorizontalAlignment="Center" Height="120" Width="120" Fill="{Binding Model.Color, Converter={StaticResource intToBrushConverter}, FallbackValue=Black}"/>
<Button Grid.Row="1" Content="Click me!" Click="Button_Click" />
</Grid>
</Window>
IntToBrushConverter.cs
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace WpfApp1
{
public class IntToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is ColorViewModel)
{
var color = value as ColorViewModel;
return new SolidColorBrush(Color.FromRgb(color.Red, color.Green, color.Blue));
}
throw new NotSupportedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
ParentViewModel.cs
using System.ComponentModel;
namespace WpfApp1
{
public class ParentViewModel : INotifyPropertyChanged
{
private ColorViewModel color;
public ColorViewModel Color
{
get { return color; }
set
{
if (color != value)
{
if (color != null)
color.PropertyChanged -= this.ChildPropertyChanged;
color = value;
if (color != null)
color.PropertyChanged += this.ChildPropertyChanged;
RaisePropertyChanged("Color");
}
}
}
private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (Color == sender)
{
RaisePropertyChanged("Color");
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
ColorViewModel.cs
using System.ComponentModel;
namespace WpfApp1
{
public class ColorViewModel : INotifyPropertyChanged
{
private byte red;
public byte Red
{
get { return red; }
set
{
if (red != value)
{
red = value;
RaisePropertyChanged("Red");
}
}
}
private byte green;
public byte Green
{
get { return green; }
set
{
if (green != value)
{
green = value;
RaisePropertyChanged("Green");
}
}
}
private byte blue;
public byte Blue
{
get { return blue; }
set
{
if (blue != value)
{
blue = value;
RaisePropertyChanged("Blue");
}
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
App.xaml和App.xaml.cs是模板生成的标准。
输出
希望它有所帮助!
答案 1 :(得分:0)
问题是Rectangle只侦听PropertyChanged
的{{1}}事件,而不是三种颜色属性。
尝试使用Model
或Model
为RaisePropertyChanged("Model");
本身举办活动。