none
Mvvm 与 DataGridCheckBoxColumn RRS feed

  • 问题

  • 我在应用MvvM方式时有二个问题?
    1,我有一个DataGrid,有一列DataGridCheckBoxColumn,我希望做到,单选某一行的CheckBox时,能指定执行Command,怎么做到呢?
    (请注意,不是在Header弄一个先选,否选)

    2,见代码,为什么SingleCommand没有执行呢?
          <DataGridTemplateColumn CanUserSort="False" HeaderStyle="{StaticResource chkAll}">
                     <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <CheckBox Command="{Binding SingleCommand}"></CheckBox>
                            </DataTemplate>
                     </DataGridTemplateColumn.CellTemplate>
          </DataGridTemplateColumn>

    2013年12月4日 2:46

答案

  • 不行啊,DataGridCheckBoxColumn 没有Command,甚至没有Click,Checked,Unchecked等事件

    一是在 IsSelect 属性 set 时候调用你想触发的代码

    二是参加:

    <Grid.Resources>          
                <DataTemplate x:Key="DateTemplate" >
                    <TextBlock Text="{Binding Path=IsSelect, Mode=OneWay}"></TextBlock>
                </DataTemplate>
               
                <DataTemplate x:Key="EditingDateTemplate">               
                    <CheckBox IsChecked="{Binding Path=IsSelect, Mode=TwoWay}"></CheckBox>
                </DataTemplate>
            </Grid.Resources>

    把这个

    <DataTemplate x:Key="DateTemplate" >
                    <TextBlock Text="{Binding Path=IsSelect, Mode=OneWay}"></TextBlock>
                </DataTemplate>

    模板修改为显式 "∨"和"×",可以自己绘制,也可以绑定背景图片,自定义 IValueConverter 实现在 bool 和 BitmapImage 之间转换。

    三是,自定义 DataGridCheckBoxColumnEx 控件,从 DataGridBoundColumn 继承,然后把 DataGridCheckBoxColumn 源码拷过来,同时再把内嵌的 CheckBox 的你需要的事件暴露出来。

    • 已标记为答案 Kyle2ms 2013年12月4日 8:52
    2013年12月4日 8:10

全部回复

  • 应该是没有正确设置路径的问题,你可以参考下面的代码,也可以去网上找找 RelativeSource 的使用。

    <dg:DataGrid

        <dg:DataGrid.RowDetailsTemplate>
                <DataTemplate>

                    <Grid Margin="10">

    <StackPanel Grid.Column="2"
                                        Orientation="Horizontal"
                                        HorizontalAlignment="Right"
                                        VerticalAlignment="Top">                         
                                <Button Content="立即发送"
                                        Style="{DynamicResource glassButtonStyler}"
                                        Height="28"
                                        Width="80"
                                        Margin="0,0,20,0"
                                        Command="{Binding Path=DataContext.SendCommand,RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}}"
                                        CommandParameter="{Binding ElementName=MessageList, Path=SelectedItem}" />
                                <Button Content="保存修改"
                                        Style="{DynamicResource glassButtonStyler}"
                                        Height="28"
                                        Width="80"
                                        Command="{Binding Path=DataContext.SaveCommand,RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}}"
                                        CommandParameter="{Binding ElementName=MessageList, Path=SelectedItem}" />
                            </StackPanel>


    • 已编辑 Skyseer 2013年12月4日 3:28
    • 已标记为答案 Kyle2ms 2013年12月4日 4:17
    • 取消答案标记 Kyle2ms 2013年12月4日 4:59
    2013年12月4日 3:26
  • DroidXgnaW 你是对的,,,谢谢了

    <CheckBox Command="{Binding DataContext.SingleJobSelectCommand, 
                                               RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
           HorizontalAlignment="Center" VerticalAlignment="Center" >



    2013年12月4日 4:17
  • 接上面的例子,
    一个新的问题,定制了二列都绑定到同一属性,第一列没有TwoWay效果,只有OneWay效果。第二列一点问题没有。
    这第一列问题出在哪?


    Joblist 和 IsSelect都有 NotifyPropertyChanged方法

             <DataGrid ItemsSource="{Binding JobList, Mode=OneWay}" AutoGenerateColumns="False" >
                            <DataGrid.Columns>
                                <DataGridTemplateColumn CanUserSort="False" HeaderStyle="{StaticResource chkAll}"  >
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <CheckBox IsChecked="{Binding IsSelect, Mode=TwoWay}" 
                                                      Command="{Binding DataContext.SingleJobSelectCommand, 
                                                                                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                                      HorizontalAlignment="Center" VerticalAlignment="Center" >
                                            </CheckBox>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
        <DataGridTextColumn Binding="{Binding IsSelect, Mode=TwoWay}" Header="H2" />
    </DataGrid.Columns>

    2013年12月4日 4:58
  • 没看明白,只看到 TwoWay,还有,你说的“效果”是什么意思?
    2013年12月4日 5:04
  • 第一列我设的是TwoWay,但前台CheckBox的勾选与否,都不影响IsSelect的值,据观察,后台修改IsSelect,前台CheckBox会变化

    第二列我设的也是TwoWay,在前台我修改False or True,IsSelect都会跟着变化

    问题就是第一列为什么TwoWay失效?

    2013年12月4日 5:11
  • 第一列我设的是TwoWay,但前台CheckBox的勾选与否,都不影响IsSelect的值,据观察,后台修改IsSelect,前台CheckBox会变化

    第二列我设的也是TwoWay,在前台我修改False or True,IsSelect都会跟着变化

    问题就是第一列为什么TwoWay失效?


    <Grid>
            <Grid.Resources>          
                <DataTemplate x:Key="DateTemplate" >
                    <TextBlock Text="{Binding Path=IsSelect, Mode=OneWay}"></TextBlock>
                </DataTemplate>
               
                <DataTemplate x:Key="EditingDateTemplate">               
                    <CheckBox IsChecked="{Binding Path=IsSelect, Mode=TwoWay}"></CheckBox>
                </DataTemplate>
            </Grid.Resources>

           
            <DataGrid AutoGenerateColumns="False" Height="239" HorizontalAlignment="Left" Margin="62,54,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="479"
                      IsSynchronizedWithCurrentItem="True"
                      ItemsSource="{Binding JobList, Mode=OneWay}">
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="H1"
                                            CellTemplate="{StaticResource DateTemplate}"
                                            CellEditingTemplate="{StaticResource EditingDateTemplate}" />
                    <DataGridTextColumn Binding="{Binding Path=IsSelect, Mode=TwoWay}" Header="H2" />
                   
                </DataGrid.Columns>
            </DataGrid>
        </Grid>

    是因为编辑框的 Editing 状态问题,上面的代码可以激活此状态,这样 CheckBox 的 Checked 状态才能传递。你可以修改 Key="DateTemplate" 这个模板,用来绘制选中和不选中状态。

    DataGrid 有 DataGridCheckBoxColumn ,你可以直接使用。

    2013年12月4日 7:00
  • 大概知道原因了,,,CellTemplate是只读模板,不会影响后台数据,所以第一列TwoWay是无效的

    那怎么样达到下面的终极目标呢?

    DataGrid 包含一列CheckBoxColumn绑定到后台数据,使得

    1,Binding mode=TwoWay

    2,任一行CheckBox的选中 or 否选 事件可以绑定到Command



    • 已编辑 Kyle2ms 2013年12月4日 7:21
    2013年12月4日 7:20
  • 大概知道原因了,,,CellTemplate是只读模板,不会影响后台数据,所以第一列TwoWay是无效的

    那怎么达到一个终极目标就是

    DataGrid 包含一列CheckBoxColumn

    1,Binding mode=TwoWay

    2,任一行CheckBox的选中 or 否选 事件可以绑定到Command



    DataGrid 有 DataGridCheckBoxColumn  ,你可以直接使用。
    2013年12月4日 7:21
  • 不行啊,DataGridCheckBoxColumn 没有Command,甚至没有Click,Checked,Unchecked等事件
    • 已编辑 Kyle2ms 2013年12月4日 7:56
    2013年12月4日 7:55
  • 不行啊,DataGridCheckBoxColumn 没有Command,甚至没有Click,Checked,Unchecked等事件

    一是在 IsSelect 属性 set 时候调用你想触发的代码

    二是参加:

    <Grid.Resources>          
                <DataTemplate x:Key="DateTemplate" >
                    <TextBlock Text="{Binding Path=IsSelect, Mode=OneWay}"></TextBlock>
                </DataTemplate>
               
                <DataTemplate x:Key="EditingDateTemplate">               
                    <CheckBox IsChecked="{Binding Path=IsSelect, Mode=TwoWay}"></CheckBox>
                </DataTemplate>
            </Grid.Resources>

    把这个

    <DataTemplate x:Key="DateTemplate" >
                    <TextBlock Text="{Binding Path=IsSelect, Mode=OneWay}"></TextBlock>
                </DataTemplate>

    模板修改为显式 "∨"和"×",可以自己绘制,也可以绑定背景图片,自定义 IValueConverter 实现在 bool 和 BitmapImage 之间转换。

    三是,自定义 DataGridCheckBoxColumnEx 控件,从 DataGridBoundColumn 继承,然后把 DataGridCheckBoxColumn 源码拷过来,同时再把内嵌的 CheckBox 的你需要的事件暴露出来。

    • 已标记为答案 Kyle2ms 2013年12月4日 8:52
    2013年12月4日 8:10
  • 多谢了,三种方案都举有可行性。
    在我的项上目中
    1,因为IsSelect是内层属性,不方便外层调用(外好几层,感觉别扭)
    2,测试过,要单击二次,体验不大好,但,是可行的
    3,稍显复杂,且在XAML上不能使用这个扩展控件,只能后台绑定吧?

    本来,想通过修改Style的方法,但是,我导出DataGridBoxColumn的默认模板,发现也挺简单的,可就是调试不出要求的效果。是否方向不对

    哎,水平不限

    2013年12月4日 9:10
  • 好吧,其实还有一种方案,,,每次CheckBox的变化,双向绑定到后台数据,另做一个Button,绑定Command,做一些前台数据变化后,关联的动作
    2013年12月4日 9:19