【问题标题】:Xaml, button's click event runs before command?Xaml,按钮的单击事件在命令之前运行?
【发布时间】:2018-05-05 05:00:02
【问题描述】:

(现在我正在学习 MVVM)我正在尝试使用来自 UI 的输入数据更新当前数据(在视图模型中)。 但问题是 ViewModel 不知道 View。这样我就无法访问 UI 中的输入数据(如 TextBox.Text)。

(下)在MainPage.xaml中包含两个TextBoxes来获取输入数据 和一个保存输入数据的按钮

<StackPanel>
        <TextBox x:Name="NameTextBox" Margin="10" Header="Name text box" />
        <TextBox x:Name="AgeTextBox" Margin="10" Header="Age text box"/>

        <StackPanel Orientation="Horizontal">

            <Button x:Name="SaveButton" Content="&#xE105;" FontFamily="Segoe MDL2 Assets"  Margin="30,10"
                     CommandParameter="{x:Bind ViewModel.CreatedPerson, Mode=OneWay}"
                     Command="{x:Bind ViewModel.SaveCommand}"
                     Click="SaveButton_Click"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="20">
            <TextBlock Text="{x:Bind ViewModel.Person.Name, Mode=OneWay}" />
            <TextBlock Text="{x:Bind ViewModel.Person.Age, Mode=OneWay}" />
        </StackPanel>
    </StackPanel>

NameTextBoxAgeTextBox 保存输入数据,直到点击 SaveButton

Person 是具有姓名和年龄属性的纯数据模型)

注意:SaveButton 上面有 CommandClick 事件

(下)MainPageViewModel.cs中包含两个属性和命令逻辑

public class MainPageViewModel : ViewModelBase
{
    public Person Person
    {
        get => _person;
        set { Set(nameof(Person), ref _person, value); }
    }
    private Person _person;

    public Person CreatedPerson
    {
        get => _createdPerson;
        set { Set(nameof(CreatedPerson), ref _createdPerson, value); }
    }
    private Person _createdPerson;

    public MainPageViewModel()
    {
        Person = new Person();
    }

    private RelayCommand<Person> _saveCommand;
    public RelayCommand<Person> SaveCommand
    {
        get
        {
            return _saveCommand
                ?? (_saveCommand = new RelayCommand<Person>(
                p =>
                {
                    Person.Name = p.Name;
                    Person.Age = p.Age;
                }));
        }
    }
}

MainPageViewModel 包含 PersonCreatedPerson 属性。 Person 属性包含当前数据。 CreatedPerson 属性包含来自 UI 的临时数据。 如果SaveButton被点击Person属性被更新。

(下)在MainPage.xaml.cs(代码隐藏文件)中有ViewModel和SaveButton_Click事件

public sealed partial class MainPage : Page
{
    private readonly MainPageViewModel ViewModel = new MainPageViewModel();

    public MainPage()
    {
        this.InitializeComponent();
    }

    private void SaveButton_Click(object sender, RoutedEventArgs e)
    {
        var newPerson = new Model.Person
        {
            Name = NameTextBox.Text,
            Age = Convert.ToInt32(AgeTextBox.Text)
        };
        ViewModel.CreatedPerson = newPerson;
    }
}

SaveButton_Click 事件从 TextBox 中获取数据并将它们保存在 ViewModel 中。

我的问题是如何将 UI 数据(在 TextBox 中)作为 SaveCommand 的参数传递? MainPageViewModel 不知道视图中的文本框。

为了解决这个问题,我在代码隐藏中创建了SaveButton_Click 事件来访问 TextBoxes 数据。 SaveButton_Click 从 TextBoxes 中获取数据并将它们保存到 ViewModel(在 CreatedPerson 属性中)。

设置CreatedPerson 后,ViewModel 中的SaveCommand 执行更新Person 属性。

因此,当单击SaveButton 时,SaveButton_Clicked 事件在SaveCommand 之前触发。所以我的项目无论如何都运行良好,但它闻起来很香。

  1. 如何以正确的方式解决此问题? 使用转换器? 现在我正在尝试使用转换器传递CommandParameter,但卡住了。 SaveCommand 需要Person 对象作为参数,Person 对象需要两个数据(姓名和年龄)。如何将两个参数传递给转换器?使用Tuple? :(

  2. 奇怪的是,click 事件总是在 Command 之前触发?

【问题讨论】:

    标签: c# xaml mvvm uwp-xaml


    【解决方案1】:

    在类后面的代码中通过构造函数设置视图模型对象。

    您不应该同时使用 Command 和 Click-event。

    【讨论】:

      【解决方案2】:

      在您的命令中,您可以使用参数参数(不打算使用 phun)

      public void Execute(object parameter)
      {
          viewModel.Reply1 = new Models.Reports.Reply();
          viewModel.ShowList = false;
      }
      

      在您的 XAML 中,您可以这样提供该参数:

          <Button Command="{Binding UpdateCommand}" CommandParameter="TheParameterYouWantoToUseInTheExecute"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-11
        • 2018-08-11
        • 2019-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多