【问题标题】:MVVM changing grid's background color on clickMVVM 在单击时更改网格的背景颜色
【发布时间】: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*/
        }
    }
}

对不起,我的英语不好。

最好的问候。

【问题讨论】:

    标签: c# wpf visual-studio xaml mvvm


    【解决方案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 中将其转换为画笔。

    1. 为 ViewModel 的属性添加新枚举:

      public enum GridState { Valid, Invalid }
      
    2. 更改属性类型:

      private GridState _gridBackground;
      public GridState GridBackground
      { 
          get { return _gridBackground; }
          set
          {
              _gridBackground = value;
              NotifyPropertyChanged();
          }
      }
      
    3. 使用值转换器添加新类

      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
      }
      
    4. 向您的控件添加新的静态资源

       <UserControl.Resources>
           <converters:GridStateToBackgroundColorConverter x:Key="gridStateToBackgroundColorConverter" />
       </UserControl.Resources>
      
    5. 更新绑定到您的属性

      <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在同一个项目吗?我在这里找到了一条指令:stackoverflow.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 不能与类型参数一起使用。
    猜你喜欢
    • 2021-01-04
    • 2021-01-26
    • 2019-09-01
    • 2014-06-12
    • 2013-11-28
    • 2011-06-05
    • 2019-12-22
    • 1970-01-01
    相关资源
    最近更新 更多