【问题标题】:Datagrid - apply changes but CellTemplate with current dataDatagrid - 应用更改,但 CellTemplate 与当前数据
【发布时间】:2015-05-07 09:54:10
【问题描述】:

我正在尝试创建一个 DataGrid,用户可以在其中编辑数据并在之后应用 oder 取消更改。 另外一个DataGridCell 有一个TemplateSelector 来帮助用户输入有效数据。 (DateTime, Boolean,...) 我的模型有一些属性。对于我的问题,有两个相关的: Model.TypeModel.Value

在 CodeBehind 中,我的属性具有以下类型:

enum Type;
string Value;

当用户编辑 Value 时,TemplateSelector 应该根据 Type 获得正确的 DataTemplate

我的 XAML 如下所示:

    <DataGrid x:Name="datagrid"                       
                      ItemsSource="{Binding Variables}"                       
                      HorizontalAlignment="Stretch"                       
                      VerticalAlignment="Stretch"                       
                      AutoGenerateColumns="False"                                  
                      IsSynchronizedWithCurrentItem="True">
                <DataGrid.Columns>
                    <DataGridComboBoxColumn Header="{StaticResource VariablesType}" 
                                            ItemsSource="{Binding Source={StaticResource VariableTypes}, Mode=OneWay}" 
                                            SelectedItemBinding="{Binding Type}" 
                                            Width="80"/>
                    <DataGridTemplateColumn Header="{StaticResource VariablesValue}" Width="2*">
                        <DataGridTemplateColumn.CellEditingTemplateSelector>
                            <TemplateSelector:TemplateSelector_Variables>
                                <!--Definitin of Templates,..-->
                            </TemplateSelector:TemplateSelector_Variables>
                        </DataGridTemplateColumn.CellEditingTemplateSelector>
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Value}"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
     </DataGrid>

让我们进入 TemplateSelector:

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item == null)
            return base.SelectTemplate(item, container);
        RaVariableType VariablenType = ((RaVariable)item).Type;
        //SelectingLogic
        //Here I would need the CURRENT type but it gives me the type of my Model
    }

我已经有了解决办法: 如果我使用:

SelectedItemBinding="{Binding Type, UpdateSourceTrigger="PropertyChanged"}"

它可以工作,但我想处理用户的 OKCancel,并且此代码更改了我的模型。

另一个问题: 你如何处理这样的决定。 (如何更新模型-命令的代码)

谢谢!

【问题讨论】:

    标签: c# wpf xaml binding datagrid


    【解决方案1】:

    您是否使用 MVVM 模式。您需要在视图模型中处理它,只需将按钮绑定到 DataGrid 的 SelectedItem 并在调用命令时使用它。做这种事情的理想方法是使用命令(基本上是 MVVM 模式),您可以在数据对象(ViewModel)中创建一个命令并调用 Button.Command ,这样就不会像 Button click 那样出现任何代码。

    此处显示示例

    <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <Button 
                          Command="{Binding   Path=DataContext.OKCommand,       
    RelativeSource= {RelativeSource FindAncestor,
    AncestorType={x:Type DataGrid}}}">
                            </Button>
                        </StackPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
    

    查看型号代码

     RelayCommand _okCommand;
    public ICommand okCommand
    {
        get
        {
            if (_ok == null)
            {
                _ok= new RelayCommand(param => this.Show());
            }
            return _ok;
        }
    }
    
    private void Show()
    {
        if (Parent != null)
        {
            // Handle ok logic Here
        }
    }
    

    您是否使用任何模式(如 Ninject、Unity 等)和实体框架来处理您的数据库层代码?您的视图模型将包含属性,并且网格的列名应该来自模型属性。一旦属性值更改,您可能需要使用 EF 或 linq to sql db 代码编写保存逻辑。保存逻辑将由单独的类处理,如果用户单击按钮,您的视图模型应该调用接口方法并进行保存。处理保存逻辑的类的实例将由 Unity 或 Ninject 提供(取决于您的实现)。您的依赖项将被注入到您的视图模型中,并且您的视图模型将公开视图绑定的属性。

    用于将所选项目从网格传递到模型 在 ViewModel 中创建一个 Property 用于保存选定的用户: public User SelectedUser { get;放; }

    将数据网格视图的 SelectedItem 绑定到此属性:SelectedItem="{Binding SelectedUser}"

    有几种方法可以选择 DataGrid 中的项目。这取决于哪一个最适合您的情况

    首先也是最基本的是 SelectedIndex,这将只选择 DataGrid 中该索引处的行

    <DataGrid SelectedIndex="{Binding SelectedIndex}" />
    
    private int _selectedIndex;
    public int SelectedIndex
    {
    get { return _selectedIndex; }
    set { _selectedIndex = value; NotifyPropertyChanged("SelectedIndex"); }
    }
    

    SelectedIndex = 2;

    SelectedItem 将选择与您设置的行匹配的行

    <DataGrid SelectedItem="{Binding SelectedRow}" />
    
    private DataRow _selectedRow;
    public DataRow SelectedRow
    {
    get { return _selectedRow; }
    set { _selectedRow = value; NotifyPropertyChanged("SelectedRow");}
    }
    
    SelectedRow = items.First(x => x.whatever == something);
    

    最常见的是设置了SelectedValuePath的SelectedValue,在这种情况下你设置你要选择的列,然后通过设置相应的值来选择行

    <DataGrid SelectedValuePath="Size Quantity" SelectedValue="{Binding SelectionValue}" 
    
    private string _selectedValue
    public string SelectionValue 
      {
    get { return _selectedValue; }
    set { _selectedValue = value; NotifyPropertyChanged("SelectionValue"); }
    }
    
    SelectionValue = "Blue";
    

    XAML 示例

    <Window x:Class="WpfApplication21.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="202" Width="232" Name="UI">
    
    <Grid DataContext="{Binding ElementName=UI}">
        <DataGrid SelectedValuePath="Size Quantity"        
                  SelectedValue="{Binding SelectionValue}" 
                  SelectedIndex="{Binding SelectedIndex}"
                  ItemsSource="{Binding SizeQuantityTable}"
                  AutoGenerateColumns="True" 
                  Margin="0,0,0,41" />
        <StackPanel Orientation="Horizontal" Height="37" VerticalAlignment="Bottom" >
            <Button Content="SelectedIndex" Height="26"  Width="107" Click="Button_Click_1"/>
            <Button Content="SelectedValue" Height="26"  Width="107" Click="Button_Click_2"/>
        </StackPanel>
    </Grid>
    </Window>
    

    【讨论】:

    • 感谢您的快速回复,但我认为您完全误解了我的问题。我知道如何处理 OK-Command 等等 - 认为我不知道如何从现有数据网格数据更新我的模型的代码。还有主要问题——如何根据当前项目编辑选择正确的数据模板。
    • 感谢您的详细解答!我没有任何数据库模式,因为我只是通过 XML 文件将数据一次获取到 ObservableCollection 中。然后我的用户可以编辑这个 ObservableCollection 并且当他点击保存按钮时,我想用我的 DataGrid 的集合来更新我的 ObservableCollection。我会这样做:BindingMode - 显式获取每个单元格 - 获取 BindingExpression - 更新源。这是好还是丑?
    • 没关系,但是如果您通过向数据库表中添加更多列来更改数据库逻辑,则需要再次更改 wpf 代码。因此,如果您使用模式执行此操作,您将拥有关注点分离的优势,并且您不必担心每次数据库更改时都会更改演示代码。
    • xml 有没有模式?
    • 数据可以来自任何地方,依赖注入将处理关注点的分离。如果您的数据是 xml,您可以使用 Linq to XML 处理保存逻辑。您可以在线获得大量关于 linqtoxml 的教程
    猜你喜欢
    • 2013-09-13
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多