【问题标题】:WPF Trigger Button CanExecute outside ItemsControl from within ItemsControlWPF 触发按钮可以在 ItemsControl 之外从 ItemsControl 执行
【发布时间】:2017-08-22 06:23:58
【问题描述】:

我正在尝试从 WPF MVVM 教程扩展应用程序作为练习。对于我在这里面临的这个特定问题,我在网上没有找到解决方案。

我有一个名为“StudentsToAdd”的带有 ObservableCollection 的 ViewModel。此集合绑定到 ItemsControl。在 ItemsControl 之外,我有一个与 ViewModel 中的“AddCommand”命令绑定的按钮。我的 XAML 的相关提取表单如下所示:

<StackPanel Orientation="Vertical">
    <StackPanel Orientation="Horizontal">
        <Button Content="Add" Command="{Binding AddCommand}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"/>
        <Button Content="+" Command="{Binding AddToAddListCommand}" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="3,0,3,0" Margin="50,0,0,0"/>
        <Button Content="-" Command="{Binding RemoveFromAddListCommand}" HorizontalAlignment="Center" VerticalAlignment="Center" Padding="5,0,5,0" Margin="5,0,0,0"/>
    </StackPanel>
    <ItemsControl x:Name="AddList" ItemsSource="{Binding Path=StudentsToAdd}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBox Text="{Binding Path=FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="0 5 3 5">
                        <TextBox.InputBindings>
                            <KeyBinding Command="{Binding ElementName=AddList, Path=DataContext.AddCommand}" Key="Return"/>
                        </TextBox.InputBindings>
                    </TextBox>
                    <TextBox Text="{Binding Path=LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="0 5 3 5">
                        <TextBox.InputBindings>
                            <KeyBinding Command="{Binding ElementName=AddList, Path=DataContext.AddCommand}" Key="Return"/>
                        </TextBox.InputBindings>
                    </TextBox>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</StackPanel>

+ 和 - 按钮将在 StudentsToAdd 集合中添加或删除学生。 “AddCommand”在执行时会将所有条目从 StudentsToAdd 移动到另一个名为“Students”的集合中。

现在我无法开始工作的是:每当修改 StudentsToAdd 中的学生时(在任何击键后:UpdateSourceTrigger=PropertyChanged)。我希望添加按钮在 ViewModel 中评估 AddCommand 的 CanExecute,以便相应地自动设置其 IsEnabled 属性。 ViewModel 中的命令方法目前如下所示:

private void OnAdd()
{
    foreach (Student s in StudentsToAdd)
    {
        Students.Add(s);
    }
    StudentsToAdd.Clear();
    StudentsToAdd.Add(new Student { FirstName = string.Empty, LastName = string.Empty });
}

private bool CanAdd()
{
    if (StudentsToAdd != null && StudentsToAdd.Count > 0)
    {
        return StudentsToAdd.All(x => !string.IsNullOrWhiteSpace(x.FirstName) && !string.IsNullOrWhiteSpace(x.LastName));
    }
    return false;
}

有人知道我如何在不耦合 MVVM 部分的情况下实现这一目标吗?

【问题讨论】:

    标签: c# wpf xaml mvvm


    【解决方案1】:

    有人知道我如何在不耦合 MVVM 部分的情况下实现这一目标吗?

    您的问题没有太多上下文。但是,您似乎在问如何完全在视图模型/模型层内完成此操作,而不涉及视图层。至少,这是你应该问的。

    如果是这样,那应该比较简单,假设你没有展示的代码写的很合理。也就是说,由于您的CanAdd() 方法依赖于Student 对象的属性值,因此您需要订阅Student.PropertyChanged 事件,并在任何Student 对象的任何时间引发ICommand.CanExecuteChanged 事件引发PropertyChanged 事件。

    对于它的价值,我还将“可添加”逻辑封装在 Student 类中,而不是 ViewModel 类中。将该状态公开为ViewModel 类可以检查的单个属性。这将解决几个问题:

    1. 您的Student 类似乎是放置代码的更合乎逻辑的位置,用于确定该类是否已准备好添加到Students 列表中,并且
    2. ViewModel 类可以检查以确保更改的是该属性,因此每次任何Student 属性更改时,它都不会费心去检查所有其他Student 对象, 并且每个Student 对象将有效地缓存“可以添加”值,因此检查所有其他Student 对象的工作是一个简单的属性检索,而不必重新每次都评估状态。

    我假设您已经了解如何引发 ICommand.CanExecuteChanged 事件,但如果没有,这里有几篇文章应该可以帮助您:

    CanExecuteChanged event of ICommand
    ICommand CanExecuteChanged not updating

    (您会看到有两个基本策略:在ICommand 对象中实现一些将显式引发ICommand.CanExecuteChanged 事件的东西,或者调用InputManager.InvalidateRequerySuggested() 来强制输入管理器调用所有CanExecute()它知道的方法。恕我直言,后者是一种重量级且不太理想的方法,因此我建议使用ICommand.CanExecuteChanged 事件。)

    【讨论】:

    • 我怎么没想到呢?这很明显,而且效果很好。唯一的缺点是在 StudentToAdd 集合中添加或删除学生时,ViewModel 中的 Student.PropertyChanged 事件会不断地挂接和取消挂接。
    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 2011-08-19
    • 2013-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    相关资源
    最近更新 更多