我想根据布尔值更改矩形的填充。我有以下课程。
扩展INotifyPropertyChanged的基类:
public class PropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
型号:
public class ChangingVariable : PropertyChangedBase
{
public ChangingVariable()
{
Variable = true;
}
private bool _variable;
public bool Variable
{
get
{
return _variable;
}
set
{
if (_variable.CompareTo(value) != 0)
{
_variable = value;
OnPropertyChanged();
}
}
}
}
视图模型:
public class BooleanRectangleViewModel : PropertyChangedBase
{
public ChangingVariable Model { get; set; }
}
这是我的不工作的视图(填充为灰色):
XAML:
<UserControl.DataContext>
<viewModels:BooleanRectangleViewModel x:Name="ViewModel"/>
</UserControl.DataContext>
<Rectangle x:Name="Rectangle">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Gray" />
<Style.Triggers>
<DataTrigger Binding="{Binding Model.Variable}" Value="true">
<Setter Property="Fill" Value="GreenYellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
CS:
public partial class BooleanRectangleView
{
public BooleanRectangleView()
{
InitializeComponent();
ViewModel.Model = new ChangingVariable();
}
}
但是当我更改它以使数据上下文是Model而不是ViewModel时,它可以工作(Fill为绿色):
XAML:
<UserControl.DataContext>
<models:ChangingVariable x:Name="ViewModel" />
</UserControl.DataContext>
<Rectangle x:Name="Rectangle">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Gray" />
<Style.Triggers>
<DataTrigger Binding="{Binding Variable}" Value="true">
<Setter Property="Fill" Value="GreenYellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
CS:
public partial class BooleanRectangleView
{
public BooleanRectangleView()
{
InitializeComponent();
ViewModel = new ChangingVariable();
}
}
为什么它不适用于中间的ViewModel?
答案 0 :(得分:2)
你想要的是颜色转换的bool,所以我会写这个类:
public class BooleanToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var isTrue = (bool) value;
if (isTrue)
return new SolidColorBrush(Colors.Green);
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
然后在你的XAML绑定中建议这个转换器。有关使用valueconverters的完整文档,请查看此处: http://www.wpf-tutorial.com/data-binding/value-conversion-with-ivalueconverter/
答案 1 :(得分:1)
据我所知,当您在模板或样式中进行绑定时,最好使用RelativeSource
。我不是绝对肯定,但你可以尝试:
<Rectangle x:Name="Rectangle">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="Gray" />
<Style.Triggers>
<DataTrigger Binding="{Binding DataContext.Model.Variable, RelativeSource={RelativeSource AncestorType=UserControl}}" Value="true">
<Setter Property="Fill" Value="GreenYellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
我对WPF / MVVM也很陌生,但我想分享一下我在短短两到三个月内学到的东西,这可能有助于其他人解决绑定问题。
每当绑定不起作用时,最可能的原因是绑定引擎无法找到绑定源或源属性。实现INotifyPropertyChanged
(或使用DependencyProperty
)只是提供了一种方法,可以在源属性的值发生更改时通知绑定。如果删除该部分,绑定将像OneTime
模式一样工作。原因很简单 - 绑定引擎足够智能,知道它必须从source属性中获取值才能使target属性起作用。
例如,您有<Border BorderBrush="{Binding MyBorderColor}" ....>
。当您的控件即将渲染时,控件需要知道边框的颜色,否则无法继续渲染。绑定引擎被强制搜索源属性MyBorderColor
。如果绑定失败,则BorderBrush
目标属性将不会获得值,这将导致Border使用任何默认值或继承值。如果MyBorderColor
没有实施&#39; INotifyPropertyChanged&#39;也不是DependencyProperty
,那么如果MyBorderColor
在运行时期间更改值一段时间,它将不会反映在BorderBrush
中,因为绑定引擎不知道源属性已更改。
答案 2 :(得分:1)
您的属性Model是自动属性,即它不实现getter或setter和OnPropertyChanged。尝试从
更改Model属性public ChangingVariable Model { get; set; }
到
private ChangingVariable model;
public ChangingVariable Model
{
get
{
return model;
}
set
{
model = value;
OnPropertyChanged("Model");
}
原因是自动属性不会通知UI他们已经更改。即使底层属性正在更改。你必须基本上为Model调用OnPropertyChanged方法。希望这会有所帮助。