如何使用Wpf mvvm

时间:2019-01-10 13:33:19

标签: wpf mvvm wpf-controls

请使用MVVM在WPF中解决此问题

我有一个下拉菜单,其中有5个值。 Onload下拉菜单仅需要启用第一个值,其余的则需要禁用。一旦我单击/选中下拉菜单下的第一个复选框,则需要启用所有其他禁用的复选框值以及从中选择的值下拉菜单需要显示在同一组合框(多选)中,并使用wpf MVVM架构用逗号或任何定界符分隔。

1 个答案:

答案 0 :(得分:0)

这大概可以满足您的需求。在下拉菜单(ComboBox中为各个项目定义视图模型:

public class ChoiceViewModel : ViewModelBase
{
    private string _content;
    public string Content
    {
        get => _content;
        set => Set(ref _content, value);
    }

    private bool _isChecked;
    public bool IsChecked
    {
        get => _isChecked;
        set => Set(ref _isChecked, value);
    }

    private bool _isEnabled;
    public bool IsEnabled
    {
        get => _isEnabled;
        set => Set(ref _isEnabled, value);
    }
}

ViewModelBase类来自MVVM Light Toolkit。它定义了我上面使用的Set方法,只要属性更改,它就会引发INotifyPropertyChanged事件。

接下来,定义一个视图模型以包含选项列表:

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
        Choices = new ObservableCollection<ChoiceViewModel>
        {
            new ChoiceViewModel {Content = "Check to enable the others", IsEnabled = true},
            new ChoiceViewModel {Content = "Choice 1", IsEnabled = false},
            new ChoiceViewModel {Content = "Choice 2", IsEnabled = false},
            new ChoiceViewModel {Content = "Choice 3", IsEnabled = false},
            new ChoiceViewModel {Content = "Choice 4", IsEnabled = false},
        };

        Choices[0].PropertyChanged += (sender, args) =>
        {
            if (args.PropertyName == nameof(ChoiceViewModel.IsChecked))
            {
                var choice = (ChoiceViewModel)sender;
                for (var i = 1; i < Choices.Count; i++)
                    Choices[i].IsEnabled = choice.IsChecked;
                RaisePropertyChanged(nameof(ChoicesDisplay));
            }
        };

        for (var i = 1; i < Choices.Count; i++)
        {
            Choices[i].PropertyChanged += (sender, args) =>
            {
                if (args.PropertyName == nameof(ChoiceViewModel.IsChecked))
                    RaisePropertyChanged(nameof(ChoicesDisplay));
            };
        }
    }

    public ObservableCollection<ChoiceViewModel> Choices { get; }

    public string ChoicesDisplay =>
        CheckedChoices.Any()
            ? string.Join(", ", CheckedChoices.Select(x => x.Content))
            : "No choices made";

    private IEnumerable<ChoiceViewModel> CheckedChoices =>
        Choices.Skip(1).Where(x => x.IsChecked);
}

当选中或取消选中第一个选项时,视图模型将处理启用或禁用其他选项。它还可以处理所选选项的显示更新,以逗号分隔。

Window类(或任何适合您的情况)中,将DataContext设置为ViewModel

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}

XAML看起来像这样:

<ComboBox
    ItemsSource="{Binding Choices}"
    Text="{Binding ChoicesDisplay, Mode=OneWay}"
    IsEditable="True"
    IsReadOnly="True"
    >
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <CheckBox
                Content="{Binding Content}"
                IsChecked="{Binding IsChecked}"
                IsEnabled="{Binding IsEnabled}"
                />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

此解决方案可以满足您的要求,但是您可能需要修复某些问题。例如,即使一个复选框被禁用(因此您无法选中或取消选中它),您仍然可以在下拉菜单中选择它。