C# 绑定不适用于ViewModel
我想根据布尔值更改矩形的填充。我有以下课程 扩展INotifyPropertyChanged的基类:C# 绑定不适用于ViewModel,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我想根据布尔值更改矩形的填充。我有以下课程 扩展INotifyPropertyChanged的基类: public class PropertyChangedBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName
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; }
}
型号:
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; }
}
视图模型:
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:
但是,当我将其更改为数据上下文是模型而不是ViewModel时,它会起作用(填充为绿色):
xaml:
为什么它不适用于中间的ViewModel?您需要的是从布尔到颜色的转换,因此我将编写以下类:
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绑定中建议使用此转换器。有关使用ValueConverter的完整文档,请参见此处:
您需要的是从布尔到颜色的转换,因此我将编写以下类:
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绑定中建议使用此转换器。有关使用ValueConverter的完整文档,请参见此处:
据我所知,在模板或样式中进行绑定时,最好使用
相对资源。我不是绝对肯定,但你可以试试:
<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
)只是提供了一种在源属性的值更改时通知绑定的方法。如果将该部件移出,则绑定将像在一次性模式下一样工作。原因很简单-绑定引擎足够智能,知道它必须从源属性获取值才能使目标属性工作
例如,您有
。当控件即将渲染自身时,控件需要知道边框的颜色,否则无法继续渲染。绑定引擎被迫搜索源属性MyBorderColor
。如果绑定失败,BorderBrush
target属性将不会获得值,这将导致边界使用任何默认值或继承值。如果MyBorderColor
没有实现“INotifyPropertyChanged”,也不是dependencProperty
,那么如果MyBorderColor
在运行期间某个时间更改了值,它将不会反映在BorderBrush
中,因为绑定引擎不知道源属性已更改。据我所知,在模板或样式中进行绑定时,最好使用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
)只是提供了一种在源属性的值更改时通知绑定的方法。如果将该部件移出,则绑定将像在一次性模式下一样工作。原因很简单-绑定引擎足够智能,知道它必须从源属性获取值才能使目标属性工作
例如,您有
。当控件即将渲染自身时,控件需要知道边框的颜色,否则无法继续渲染。绑定引擎被迫搜索源属性MyBorderColor
。如果绑定失败,BorderBrush
target属性将不会获得值,这将导致边界使用任何默认值或继承值。如果MyBorderColor
没有实现“INotifyPropertyChanged”,也不是DependencyProperty
,那么如果MyBorderColor
在运行期间某个时间更改了值,它将不会反映在BorderBrush
中,因为绑定引擎不知道源属性已更改。您的属性模型是自动属性,即它不实现getter或setter和OnPropertyChanged。尝试从更改模型属性
public ChangingVariable Model { get; set; }
到
原因是自动属性不会通知UI它们已更改。即使基础属性正在更改。您还必须基本上为模型调用OnPropertyChanged方法。希望这有帮助。您的属性模型是自动属性,即它没有实现getter或setter和OnPropertyChanged。尝试从更改模型属性
public ChangingVariable Model { get; set; }
到
原因是自动属性不会通知UI它们已更改。即使基础属性正在更改。您还必须基本上为模型调用OnPropertyChanged方法。希望这能有所帮助。谢谢,但这并不能回答我的方法不起作用的原因。在调用PropertyChanged的地方,是否会使用属性名称触发属性更改事件?可能很容易,不,显然不是!谢谢,我必须弄清楚如何给它起正确的名字。不,不是这样,如果我调用OnPropertyChanged(“Model.Variable”)
而不是OnPropertyChanged(“Variable”)
,它仍然可以