将WPF中按钮的多个属性绑定到类

时间:2018-04-05 01:53:50

标签: wpf

我不确定这是否可行,但我正在寻找一种方法将按钮绑定到包含我需要使用的所有属性的泛型类。每个按钮都需要一个中继命令,以便包含但是我们所有的按钮都需要绑定可见性并启用。我们在给定的Windows视图模型中使用的每个按钮都没有这组属性和relay命令,我想知道是否有一种方法让按钮绑定到一个类然后在我们的视图模型中我们引用一个新的实例需要每个按钮的类,然后才能将该类的属性设置为我们需要的值。我希望这是有道理的。

1 个答案:

答案 0 :(得分:1)

可能有很多不同的方法可以做这样的事情。我不知道我是否选择为每个按钮设置一个类实例。但这是解决方案的粗略/快速/狡猾的例子。

表单的主要模型是通过列表提供按钮模型。然后单个按钮模型处理按钮绑定。

编辑:稍微扩展一下代码。现在包括命令绑定。还显示了@Xavier建议的ItemsControl的使用。希望它有所帮助。

MainWindow.xaml:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="300" Width="400">
    <StackPanel>

        <!-- Known buttons -->
        <StackPanel Margin="20">
            <Button DataContext="{Binding ButtonModels[0], Mode=OneTime}" Content="{Binding LabelText}" Background="{Binding Colour}" Command="{Binding Command}" CommandParameter="{Binding CommandParameter}" />
            <Button DataContext="{Binding ButtonModels[1], Mode=OneTime}" Content="{Binding LabelText}" Background="{Binding Colour}" Command="{Binding Command}" CommandParameter="{Binding CommandParameter}" />
            <Button DataContext="{Binding ButtonModels[2], Mode=OneTime}" Content="{Binding LabelText}" Background="{Binding Colour}" Command="{Binding Command}" CommandParameter="{Binding CommandParameter}" />
        </StackPanel>

        <!-- Dynamic buttons -->
        <StackPanel Margin="20">
            <ItemsControl ItemsSource="{Binding ButtonModels}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Button Content="{Binding LabelText}" Background="{Binding Colour}" Command="{Binding Command}" CommandParameter="{Binding CommandParameter}" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>

    </StackPanel>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new Model();
        }
    }

    public class Model
    {
        private Random rnd = new Random();
        public List<ButtonModel> ButtonModels { get; private set; }

        public Model()
        {
            this.ButtonModels = new List<ButtonModel>();
            for (int i = 0; i < 5; i++)
            {
                this.ButtonModels.Add(new ButtonModel
                {
                    LabelText = "Button " + (i + 1),
                    Command = new RelayCommand((index) => { this.ChangeColour((int)index); }),
                    CommandParameter = i
                });
            }
        }

        private void ChangeColour(int index)
        {
            this.ButtonModels[index].Colour = new SolidColorBrush(Color.FromRgb((byte)rnd.Next(50, 256), (byte)rnd.Next(50, 256), (byte)rnd.Next(50, 256)));
        }
    }

    public class ButtonModel : ObservableObject
    {
        private string _LabelText;
        public string LabelText { get => _LabelText; set => this.SetProperty(ref _LabelText, value); }

        private Brush _Colour = new SolidColorBrush(Color.FromRgb(205, 205, 205));
        public Brush Colour { get => _Colour; set => this.SetProperty(ref _Colour, value); }

        private RelayCommand _Command;
        public RelayCommand Command { get => _Command; set => this.SetProperty(ref _Command, value); }

        private int _CommandParameter;
        public int CommandParameter { get => _CommandParameter; set => this.SetProperty(ref _CommandParameter, value); }
    }

    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (field == null && value == null)
            {
                return false;
            }

            if (field == null || !field.Equals(value))
            {
                field = value;
                this.RaisePropertyChangedEvent(propertyName);
                return true;
            }

            return false;
        }

        protected void RaisePropertyChangedEvent(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class RelayCommand : ICommand
    {
        private Action<object> execute;
        private Predicate<object> canExecute;

        public event EventHandler CanExecuteChanged;

        public RelayCommand(Action<object> action, Predicate<object> canExecute = null)
        {
            this.execute = action;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return this.canExecute == null || this.canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            this.execute(parameter);
        }
    }
}