MVVM 在单击时更改网格的背景颜色

Posted

技术标签:

【中文标题】MVVM 在单击时更改网格的背景颜色【英文标题】:MVVM changing grid's background color on click 【发布时间】:2016-03-23 17:57:23 【问题描述】:

我是 MVVM 模式的真正初学者。我正在尝试在单击按钮时更改网格的背景。我有一个带有包含按钮的网格的 xaml 和一个 ViewModel .cs,我想在单击按钮时更改网格的背景。直到我点击时成功显示了一个 MessageBox...

.xaml 代码:

<Window x:Class="WpfSimple.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfSimple"
    Title="MainWindow" Height="150" Width="370">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
    <Grid>
    <Button Content="Click" 
            Height="23" 
            HorizontalAlignment="Left"
            Background="Gray"
            Margin="75.944,47.465,0,0" 
            Name="btnClick" 
            VerticalAlignment="Top" 
            Width="203"
            Command="Binding ButtonCommand"/>
        <!--What is necessary to add for changing grid color ? Commandparameter ?-->
</Grid>

MainWindowViewModel.cs 代码:

namespace WpfSimple

    class MainWindowViewModel
    
        private ICommand m_ButtonCommand;
        public ICommand ButtonCommand
        
            get
            
                return m_ButtonCommand;
            
            set
            
                m_ButtonCommand = value;
            
        

        public MainWindowViewModel()
        
            ButtonCommand=new RelayCommand(new Action<object>(ChangeBgColor));
        

        public void ChangeBgColor(object obj)
        
            /*HERE I WANT TO CHANGE GRID COLOR*/
        
    

对不起,我的英语不好。

最好的问候。

【问题讨论】:

【参考方案1】:

您最应该在 ViewModel 中实现 INotifyPropertyChanged:

public class MainWindowViewModel : INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    // This method is called by the Set accessor of each property.
    // The CallerMemberName attribute that is applied to the optional propertyName
    // parameter causes the property name of the caller to be substituted as an argument.
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    
        if (PropertyChanged != null)
        
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        
    

然后,将 NotifyPropertyChanged() 添加到您的属性设置器。

好的。接下来,将带有网格背景颜色的新属性添加到 ViewModel:

private Brush _gridBackground;
public Brush GridBackground
 
    get  return _gridBackground; 
    set
    
        _gridBackground = value;
        NotifyPropertyChanged();
    

并将您的网格背景绑定到您的属性:

<Grid Background="Binding GridBackground">

最后,您可以在命令处理程序中更改 GridBackground:

public void ChangeBgColor(object obj)

    GridBackground = Brushes.Blue;

您应该记住,将诸如 Brush 之类的 WPF 类添加到您的代码中是一种不好的做法。更好的方法是在您的 ViewModel 中的 XAML 代码和 BCL 类中使用 IValueConverter。例如,可以在 ViewModel 中使用枚举,在 ValueConverter 中将其转换为画笔。

    为 ViewModel 的属性添加新枚举:

    public enum GridState  Valid, Invalid 
    

    更改属性类型:

    private GridState _gridBackground;
    public GridState GridBackground
     
        get  return _gridBackground; 
        set
        
            _gridBackground = value;
            NotifyPropertyChanged();
        
    
    

    使用值转换器添加新类

    public class GridStateToBackgroundColorConverter : IValueConverter
    
        #region IValueConverter Members
    
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        
            GridState val = (GridState) value;
            if(val == GridState.Valid)
                return Brushes.Green;
            return Brushes.Red;
        
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        
            throw new NotSupportedException();
        
    
        #endregion
    
    

    向您的控件添加新的静态资源

     <UserControl.Resources>
         <converters:GridStateToBackgroundColorConverter x:Key="gridStateToBackgroundColorConverter" />
     </UserControl.Resources>
    

    更新绑定到您的属性

    <Grid Background="Binding GridBackground, Converter=StaticResource gridStateToBackgroundColorConverter">
    

【讨论】:

是的!非常感谢瓦迪姆·马丁诺夫!我不确定我是否理解“INotifyPropertyChanged Interface”的目的,因为它根本没有通知我......但你的回答真的很有帮助。最好的问候。 @Chefty INPC 是数据绑定所必需的。没有它,当您更改 ViewModel 中的属性时,您的颜色不会改变。此外,INPC 是数据绑定的一般特征。您可以在 MSDN 上阅读更多内容:msdn.microsoft.com/en-US/library/ms752347(v=vs.100).aspx 我无法向控件添加新的静态资源,报错:“WPF项目不支持GridStateToBackgroundColorConverter”正常吗? 完全没有。而且很难理解这个问题。 1.您的转换器是否真正实现了 System.Windows.Data 中的 IValueConverter? 2.你的converter类和view在同一个项目吗?我在这里找到了一条指令:***.com/questions/28607372/… 我认为您应该像在那个答案中一样添加转换器命名空间:xmlns:converters="clr-namespace:YourAppName.YourNamespaceWithConverter" 是的 IValueConverter 是从 System.Windows.Data 实现的,现在我无法使转换器命名空间工作。我的应用程序名称是“WpfSimple”,包含 Converter 类的命名空间也被命名为“WpfSimple”......我将您的类“GridStateToBackgroundColorConverter”复制到第一个类“MainWindowViewModel”中,因为它是我声明“GridState”变量的地方。这是个坏主意吗?【参考方案2】:

如果你想改变网格背景颜色,那么你可以使用命令参数。您可以将任何 UI 控件作为命令参数传递。在您的情况下,通过网格访问视图模型中的网格。 为您的网格命名并使用该名称作为命令参数。 为此,您需要实现如下代码:

<Window x:Class="WpfSimple.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfSimple"
        Title="MainWindow" Height="150" Width="370">
<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid Name="grid">
<Button Content="Click" 
        Height="23" 
        HorizontalAlignment="Left"
        Background="Gray"
        Margin="75.944,47.465,0,0" 
        Name="btnClick" 
        VerticalAlignment="Top" 
        Width="203"
        Command="Binding ButtonCommand"
        CommandParameter="Binding Elementname="grid""/>
</Grid>

对 .xaml 文件进行此更改后。实施参数化中继命令以使用此传递的网格在您的 Viewmodel 文件中使用。 实现参数化中继命令尝试实现以下代码:

    private ICommand m_ButtonCommand;
    public ICommand ButtonCommand
    
        get
        
            return m_ButtonCommand;
        
        set
        
            m_ButtonCommand = value;
        
    

    public MainWindowViewModel()
    
        ButtonCommand=new RelayCommand<Grid>(ChangeBgColor);
    

    public void ChangeBgColor(Grid grid)
    
        if(grid!=null)
            grid.Background = Brushes.Red; //Any color you want to change.
    

我希望这会奏效。谢谢。

【讨论】:

嗨!谢谢 Dhruv Panchal,但它不起作用。 “RelayCommand”出错,我无法解决。 @Chefty 您遇到了哪个错误?你能告诉我吗?您是否在应用程序中实现了 RelayCommand 告诉我 RelayCommand 不能与类型参数一起使用。

以上是关于MVVM 在单击时更改网格的背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

需要更改 extjs 网格操作列内图标的背景颜色

Xamarin Forms:如何为网格内单击的按钮添加背景颜色(单词搜索游戏)

DataGridView透明行选择和双击背景颜色更改

选中时更改网格行的背景颜色

javascript在单击时更改背景颜色[关闭]

单击android时更改TextView背景颜色