Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 绑定不适用于ViewModel_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 绑定不适用于ViewModel

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

我想根据布尔值更改矩形的填充。我有以下课程

扩展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; }
}
型号:

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”)
,它仍然可以