【问题标题】:WPF MVVM handle datagrid cell changeWPF MVVM 处理数据网格单元格更改
【发布时间】:2018-04-10 08:29:08
【问题描述】:

我尝试捕捉 CellEditEnding 事件并获取我的视图模型的行+列号和新值。

我试试这个How do you handle data grid cell changes with MVVM? 但我得到了这个异常

“未找到类型'GalaSoft_MvvmLight_Command'。请确认您 没有缺少程序集引用,并且所有引用程序集 已建成”。我参考了 GalaSoft.MvvmLight.WPF4.dll。

这是我的数据网格:

 <DataGrid MaxHeight="600" AutoGenerateColumns="False" VerticalScrollBarVisibility="Auto"
                  ItemsSource="{Binding BitTestParam,Mode=TwoWay}" GridLinesVisibility="None" RowBackground="{x:Null}" Background="{x:Null}"
                  BorderThickness="2" BorderBrush="Black" HeadersVisibility="Column" Foreground="Black" FontStyle="Italic" FontWeight="SemiBold">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="CellEditEnding">
                    <i:InvokeCommandAction Command="{Binding CellChangedCommand}" CommandParameter="{Binding}"/>
                    <!--<GalaSoft_MvvmLight_Command:EventToCommand PassEventArgsToCommand="True" Command="{Binding CellEditEndingCommand}"/>-->
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Input Param" Binding="{Binding InputNames}"/>
                <DataGridTextColumn x:Name="InputValuesColumn" Header="Param value" Binding="{Binding InputValues}" />
                <DataGridTextColumn Header="Output Param" Binding="{Binding OutputNames}"/>
                <DataGridTextColumn Header="Measure value" Binding="{Binding OutputValues}"/>
                <DataGridTextColumn Header="Error Messages" Binding="{Binding ErrorMessages}"/>
                <DataGridTextColumn Header="Warning Messages" Binding="{Binding WarningMessages}" />
            </DataGrid.Columns>
        </DataGrid>

这是我在 viewModel 中的相关代码:

public RelayCommand<object> CellChangedCommand
{
    get;
    set;
}

CellChangedCommand = new RelayCommand<object>(CellChangedEvent);

void CellChangedEvent(object obj)
{

}

我得到了带有参数的命令“CellChangedCommand”,但我需要得到行+列号和新值。

谢谢

【问题讨论】:

  • 我不允许在数据网格中进行编辑。我建议您考虑将数据网格设为只读。用户选择他们想要编辑的行。他们在叠加层中进行编辑并选择提交或放弃。否则验证就是一场噩梦。

标签: c# wpf mvvm


【解决方案1】:

我会让用户在单独的面板中进行编辑并在那里进行处理程序验证。 这就是这个示例的工作原理: https://gallery.technet.microsoft.com/scriptcenter/WPF-Entity-Framework-MVVM-78cdc204

在其中您会发现一些代码可以确定哪个绑定只是将数据从视图传输到视图模型。 即使用户在数据网格中进行编辑,您仍然可以使用它。 您只需要围绕数据网格的网格或面板。 它甚至可能在数据网格中工作,我必须尝试一下才能确定。 但是如果你查看项目的资源字典,你会看到:

    <Grid Visibility="{Binding IsInEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" 
           Width="{Binding ElementName=dg, Path=ActualWidth}"
           Height="{Binding ElementName=dg, Path=ActualHeight}"
           >
                <i:Interaction.Triggers>
                    <local:RoutedEventTrigger RoutedEvent="{x:Static Validation.ErrorEvent}">
                        <e2c:EventToCommand
                                                Command="{Binding EditVM.TheEntity.ConversionErrorCommand, Mode=OneWay}"
                                                EventArgsConverter="{StaticResource BindingErrorEventArgsConverter}"
                                                PassEventArgsToCommand="True" />
                    </local:RoutedEventTrigger>
                    <local:RoutedEventTrigger RoutedEvent="{x:Static Binding.SourceUpdatedEvent}">
                        <e2c:EventToCommand
                                                Command="{Binding EditVM.TheEntity.SourceUpdatedCommand, Mode=OneWay}"
                                                EventArgsConverter="{StaticResource BindingSourcePropertyConverter}"
                                                PassEventArgsToCommand="True" />
                    </local:RoutedEventTrigger>
                </i:Interaction.Triggers>

转换失败或删除它们由前者抓取,后者由后者传输数据。

您需要将绑定标记为 notifyonsourceupdated - 示例绑定是:

<TextBox Text="{Binding  EditVM.TheEntity.Address1, 
                        UpdateSourceTrigger=PropertyChanged, 
                        NotifyOnSourceUpdated=True,
                        NotifyOnValidationError=True,
                        Mode=TwoWay}"  />

如果我遗漏了什么,示例中还有其他代码。 路由事件触发器

public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
    RoutedEvent routedEvent;
    public RoutedEvent RoutedEvent
    {
        get
        {
            return routedEvent;
        }
        set 
        { 
            routedEvent = value;
        }
    }

    public RoutedEventTrigger()
    {
    }
    protected override void OnAttached()
    {
        Behavior behavior = base.AssociatedObject as Behavior;
        FrameworkElement associatedElement = base.AssociatedObject as FrameworkElement;
        if (behavior != null)
        {
            associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
        } 
        if (associatedElement == null)
        {
            throw new ArgumentException("This only works with framework elements");
        }
        if (RoutedEvent != null)
        {
            associatedElement.AddHandler(RoutedEvent, new RoutedEventHandler(this.OnRoutedEvent));
        }
    }
    void OnRoutedEvent(object sender, RoutedEventArgs args)
    {
         base.OnEvent(args);
    }
    protected override string GetEventName()
    {
        return RoutedEvent.Name;
    }
}

绑定源属性转换器

public class BindingSourcePropertyConverter: IEventArgsConverter
{
    public object Convert(object value, object parameter)
    {
        DataTransferEventArgs e = (DataTransferEventArgs)value;
        BindingExpression binding = ((FrameworkElement)e.TargetObject).GetBindingExpression(e.Property);
        return binding.ResolvedSourcePropertyName ?? "";
    }
}

【讨论】:

  • 我无法在没有额外面板的情况下绑定正在更改的单元格?我是 mvvm 的新手。有没有别的办法? tnx!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-30
  • 2016-05-12
  • 1970-01-01
相关资源
最近更新 更多