【问题标题】:Could not pass values from view to viewmodel through commands无法通过命令将值从视图传递到视图模型
【发布时间】:2018-09-19 17:43:40
【问题描述】:

我正在为我的应用程序实现 MVVM 模式。我有我的视图、视图模型、模型和命令和转换器正在实施。现在我无法通过命令绑定将我的文本框值从我的数据模板传递给我的 ViewModel。我可以单击按钮尝试更新过程,但它无法传递文本框值。我的命令类有什么需要更改的吗?

这是我的 XAML:

<DataGrid AutoGenerateColumns="False" Grid.Row="2" Grid.ColumnSpan="4" Grid.RowSpan="3" x:Name="productionLineConfigDataGrid" Margin="70,0.2,70,0" ItemsSource="{Binding listAllProductionLineConfigs}">
<DataTemplate>
<StackPanel>
        <StackPanel Orientation="Horizontal">
                <TextBlock FontSize="12" Text="ID: " VerticalAlignment="Center" />
                <TextBlock x:Name="txtBlockLineId" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineId, Mode=TwoWay}" VerticalAlignment="Center" />
        </StackPanel>
        <StackPanel>
                <Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right" Click="btnUpdate_Click" Command="{Binding DataContext.updateProductionLineConfigCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:production_line_config_home}}}" CommandParameter="{Binding ProductionLineConfig}"/>
        </StackPanel>
</StackPanel>
</DataTemplate>
</DataGrid>

这是我的 ViewModel 中的方法:

public ProductionLineConfig ProductionLineConfig
    {
        get { return productionlineconfig; }

        set
        {
            productionlineconfig = value;
            OnPropertyChanged("ProductionLineConfig");
        }
    }

这是我收到的错误消息:

System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“ProductionLineConfig”(HashCode=47309994)上找不到“ProductionLineConfig”属性。绑定表达式:路径=生产线配置; DataItem='ProductionLineConfig' (HashCode=47309994);目标元素是 'Button' (Name='');目标属性是'CommandParameter'(类型'Object')

我已经为我的应用程序添加了图片here

这是整个 xaml 代码 here 这是整个视图模型代码 here

【问题讨论】:

  • @Mac 我相信这对我的情况不起作用。
  • 您的 listAllProductionLineConfigs 是什么?这是 ProductionLineConfig 的列表吗?
  • @Mac 是的,它列出了数据网格中的所有生产线配置
  • @Mac 请查看我在问题中发布的图片链接,您可能了解我在做什么。当我点击更新按钮时,它会从我的视图模型方法中显示一个消息框,其中显示线路名称、状态和线路 ID。但目前,它没有得到任何价值

标签: c# wpf data-binding


【解决方案1】:

我只是猜测一下。

假设ProductionLineConfig 是您在模板中为ProductionLineId 绑定的内容。那么您可能只是想将绑定源作为命令参数传递

CommandParameter="{Binding}"

当{Binding} 为空时,表示Binding 绑定到任何Source。这也只是...的简写。

{Binding DataContext,RelativeSource={RelativeSource Self}}.

反过来(如果星星对齐),那么它应该是你的ProductionLineConfig

【讨论】:

  • 不客气,我刚开始回答,就看到你的回答进来了,没什么好说的了。
  • @Saruman 即使我将它绑定到自身,它仍然无法正常工作。它无法将值传递给我的视图模型。也许你想看看我的 Datagrid。我将再次编辑我的问题。
【解决方案2】:

根据您的代码源,我做了一个示例实现,以满足您的要求。

示例虚拟机:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApp5.ViewModels
{
    public class ProductionLineConfigViewModel : INotifyPropertyChanged
    {
        public CustomCommand<ProductionLineConfig> UpdateCommand { get; }

        public ProductionLineConfigViewModel()
        {
            PopulateProductionLineConfigs();
            UpdateCommand = new CustomCommand<ProductionLineConfig>(UpdateConfig, (u) => true);
        }

        private ObservableCollection<ProductionLineConfig> _listAllProductionLineConfigs;
        public ObservableCollection<ProductionLineConfig> listAllProductionLineConfigs
        {
            get { return _listAllProductionLineConfigs; }
            set
            {
                _listAllProductionLineConfigs = value;
                OnPropertyChanged();
            }
        }

        //  Call this from constructor.
        private void PopulateProductionLineConfigs()
        {
            listAllProductionLineConfigs = new ObservableCollection<ProductionLineConfig>
            {
                new ProductionLineConfig
                {
                    ProductionLineId = 1,
                    ProductionLineCode = "001",
                    ProductionLineCreatedDate = DateTime.Today.Date,
                    ProductionLineName = "safdsf",
                    ProductionLineStatus = true
                },
                new ProductionLineConfig
                {
                    ProductionLineId = 1,
                    ProductionLineCode = "002",
                    ProductionLineCreatedDate = DateTime.Today.Date,
                    ProductionLineName = "sadfadfsdf",
                    ProductionLineStatus = true
                }
            };
        }

        private void UpdateConfig(ProductionLineConfig config)
        {
            MessageBox.Show("Line Name update: " + config.ProductionLineName);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }

    public class ProductionLineConfig
    { 
        public int ProductionLineId { get; set; }

        public string ProductionLineCode { get; set; }

        public string ProductionLineName { get; set; }

        public bool ProductionLineStatus { get; set; }
        public DateTime ProductionLineCreatedDate { get; set; }
    }
}

XAML 示例:

<Window x:Name="Root" x:Class="WpfApp5.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"
        xmlns:viewModels="clr-namespace:WpfApp5.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <viewModels:ProductionLineConfigViewModel/>
    </Window.DataContext>

    <Grid Background="#FF006E8C">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Grid.ColumnSpan="4" Content="KAD ShopFloor System" HorizontalAlignment="Center" Margin="10" FontWeight="Bold" FontSize="30" FontFamily="Segoe UI" Foreground="White"/>
        <Separator Grid.ColumnSpan="4" Grid.RowSpan="3" Background="White" Margin="0,-35,-0.4,39.2"/>
        <DataGrid AutoGenerateColumns="False" Grid.Row="2" Grid.ColumnSpan="4" Grid.RowSpan="3" x:Name="productionLineConfigDataGrid" Margin="70,0.2,70,0"
                  ItemsSource="{Binding DataContext.listAllProductionLineConfigs, ElementName=Root}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding ProductionLineId, Mode=TwoWay}"/>
                <DataGridTextColumn Header="Production Line Code" Binding="{Binding ProductionLineCode, Mode=TwoWay}"/>
                <DataGridTextColumn Header="Production Line Name" Binding="{Binding ProductionLineName, Mode=TwoWay}"/>
                <DataGridTextColumn Header="Status" Binding="{Binding ProductionLineStatus, Mode=TwoWay}"/>
                <DataGridTextColumn Header="Created Date" Binding="{Binding ProductionLineCreatedDate, Mode=TwoWay}"/>
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <Border BorderThickness="0" Background="BlanchedAlmond" Padding="10">
                        <StackPanel Orientation="Vertical" x:Name="stck">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock FontSize="12" Text="ID: " VerticalAlignment="Center" />
                                <TextBlock x:Name="txtBlockLineId" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock FontSize="12" Text="Line Code: " VerticalAlignment="Center" />
                                <TextBlock x:Name="txtBlockLineCode" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineCode, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
                            </StackPanel>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock FontSize="12" Text="Line Name: " VerticalAlignment="Center" />
                                <TextBox x:Name="txtLineName" FontSize="16" Foreground="MidnightBlue" Text="{Binding ProductionLineName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" />
                            </StackPanel>
                            <!--<StackPanel Orientation="Horizontal">
                                <TextBlock FontSize="12" Text="Status: " VerticalAlignment="Center" />
                                <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}},
                                    Path=DataContext.Statusstring}" SelectedValue="{Binding ProductionLineStatus, Converter={StaticResource statusToBooleanConverter}, Mode=TwoWay}" x:Name="cbProductionLineStatus" FlowDirection="LeftToRight" FontSize="16" Foreground="MidnightBlue"
                                    HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
                            </StackPanel>-->
                            <StackPanel>
                                <Button x:Name="btnUpdate" Content="Update" VerticalAlignment="Center" HorizontalAlignment="Right"
                                        Command="{Binding DataContext.UpdateCommand, ElementName=Root}"
                                        CommandParameter="{Binding}" />
                            </StackPanel>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>

    </Grid>
</Window>

样本输出:

这里的主要变化,

  1. 您需要将列表更改为可观察集合

  2. 创建一个接受对象的自定义命令,参见这篇文章:[UWP/MVVM]Enable/Disable Button in RadDataGrid Data Template Column that have commands bound to them upon conditions

  3. Command Parameter应该是迭代项,可以通过CommandParameter={Binding}实现

  4. 在你的双向绑定中,确保添加UpdateSourceTrigger=PropertyChanged

【讨论】:

  • 你能检查一下这个答案吗?我刚刚注意到之前的答案已经谈到了命令参数。
  • 我不认为点击方法会发生冲突.. 但无论如何我已经删除了点击方法,它仍然无法将文本框值传递给我的视图模型
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
  • 2016-03-11
相关资源
最近更新 更多