【问题标题】:WPF - Command in datacontext of the window and commandparameter from listview in user controlWPF - 窗口数据上下文中的命令和用户控件中列表视图中的命令参数
【发布时间】:2021-05-23 22:31:26
【问题描述】:

按照 MVVM 模式,在我的 WPF 应用程序中运行命令的绑定时遇到了一些问题。

我目前拥有的:

带有 DataContext MainWindowViewModel 的 MainWindow。 带有 DataContext SecondPageViewmodel 的 SecondPage(用户控件)。

用户控件仅包含一个名为 StudentListView 的列表视图,绑定到 SecondPageViewModel 中的可观察集合。

主窗口有一个文本框,按回车键将触发我的命令,称为 ReturnPressCommand,它位于 MainWindowViewModel 中。主窗口还包含一个 SecondPage 用户控件的实例。

我想做的是能够使用用户控件中的 StudentListView 作为主窗口中命令 ReturnPressCommand 的命令参数。

我该如何做到这一点?

主窗口:

<Window x:Class="MVVMTEST.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MVVMTEST.ViewModels"
        xmlns:control="clr-namespace:MVVMTEST.Views"
        mc:Ignorable="d"
        Title="MainWindow" Height="800" Width="1600" WindowStartupLocation="CenterScreen">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <TextBox Grid.Column="0" Grid.Row="0" Width="120" Height="20">
            <TextBox.InputBindings>
                <KeyBinding Key="Return" 
                            Command="{Binding Path=ReturnPressCommand}" 
                            CommandParameter="{}"/>
            </TextBox.InputBindings>
        </TextBox>

        <control:SecondPage x:Name="SecondPageX" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Width="auto" Visibility="Visible"></control:SecondPage>
    </Grid>
</Window>

主窗口的视图模型

using MVVMTEST.Commands;
using System.Windows.Input;

namespace MVVMTEST.ViewModels
{
    class MainWindowViewModel
    {
        public MainWindowViewModel()
        {
            
        }

        private ICommand _returnPressCommand = null;
        public ICommand ReturnPressCommand
        {
            get
            {
                if (_returnPressCommand == null)
                    _returnPressCommand = new ReturnPressCommand();
                return _returnPressCommand;
            }
        }
    }
}

我要执行的命令

namespace MVVMTEST.Commands
{
    class ReturnPressCommand : CommandBase
    {
        public override bool CanExecute(object parameter)
        {
            return true;
        }

        public override void Execute(object parameter)
        {
            // Do operations with the observable collection
        }
    }
}

用户控件

<UserControl x:Class="MVVMTEST.Views.SecondPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MVVMTEST.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="400" d:DesignWidth="1600">

    <UserControl.DataContext>
        <local:SecondPageViewModel />
    </UserControl.DataContext>

    <Grid Background="Green">
        <ListView Grid.Column="0" Grid.Row="0" x:Name="StudentListView" ItemsSource="{Binding Students}">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name"></GridViewColumn>
                    <GridViewColumn DisplayMemberBinding="{Binding Age}" Header="Age"></GridViewColumn>
                    <GridViewColumn DisplayMemberBinding="{Binding Gpa}" Header="Gpa"></GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</UserControl>

用户控件的视图模型

using System.Collections.Generic;
using System.Collections.ObjectModel;
using MVVMTEST.Models;

namespace MVVMTEST.ViewModels
{
    public class SecondPageViewModel
    {
        public IList<Student> Students { get; } = new ObservableCollection<Student>();
        public SecondPageViewModel()
        {
            Students.Add(new Student { Name = "Firstname Lastname", Age = 25, Gpa = 0.0 });
        }
    }
}

我希望文本框始终可见,但是在未来我计划添加更多用户控件,它们的可见性将根据用户在应用程序中的操作而改变。现在我想实现一个搜索功能来过滤位于用户控件视图模型中的可观察集合中的学生。然后用户控件将列出这些过滤的学生。

【问题讨论】:

  • 你的意思是你想在你的命令参数中使用 SecondPageViewModel 的可观察集合?您的 MainViewModel 中已经有了它的实例。为什么你不能使用它呢?
  • 完全可以观察到的集合在 SecondPageViewModel 中,但是我应该澄清主窗口仅在 XAML 中包含用户控件,而不是在 MainWindowViewModel 中,例如:
  • 用户控制与此无关。它绑定到您想要的可观察集合。为什么要关注用户控制?
  • 我要做的是将命令和命令参数拆分为不同的文件。 MainWindow 有我的文本框,我在其中检查输入键。执行的命令在 MainWindowViewModel 中,而我要操作的集合在 SecondPageViewModel 中。然后我想在 SecondPage 中列出这个集合。
  • 您在这里没有多大意义,但我会尽力向您解释这一点。当您在可观察集合中更改(添加删除更新或创建)时,UI 将自动更新。您不必将其作为参数传递。只需对列表执行操作,UI 就会获取这些更改。我希望这是有道理的。

标签: c# wpf xaml data-binding wpf-controls


【解决方案1】:

您可以通过用户控件的名称将 CommandParameter 绑定到集合。

<TextBox Grid.Column="0" Grid.Row="0" Width="120" Height="20">
            <TextBox.InputBindings>
                <KeyBinding Key="Return" 
                            Command="{Binding Path=ReturnPressCommand}" 
                            CommandParameter="{Binding DataContext.Students, ElementName=SecondPageX}" />
            </TextBox.InputBindings>
</TextBox>

【讨论】:

  • 谢谢!这似乎确实有效。一个小问题是 DataContext.Students 带有下划线并显示消息:无法在“MVVMTEST.ViewModels.MainWindowViewModel”类型的数据上下文中解析属性“Students”。有任何想法吗?否则效果很好。
猜你喜欢
  • 2012-09-11
  • 2011-03-29
  • 1970-01-01
  • 1970-01-01
  • 2021-06-20
  • 1970-01-01
  • 2010-11-04
  • 2010-09-14
  • 2011-08-28
相关资源
最近更新 更多