none
Datagrid 中 DataGridTemplateColumn 的 Binding 问题 RRS feed

  • 问题

  • 我使用ObservableCollection在classA中定义了类似这样的二维数组结构:
    public class classA
    {
    	...
            public class  classBs : ObservableCollection<classB> { }
    
            private ObservableCollection<classBs > m_ ClassBInstances ;
            public ObservableCollection<classBs > ClassBInstances
            { get { return   ClassBInstances  ; } }
            ...
    }
    
    其中二维数组在class构造函数中分配空间,并且大小固定为4行3列。
    classB部分定义和如下:
    class classB :  INotifyPropertyChanged
    {
    	...
    	private bool m_bvalue;
    	public bool BValue
    	{
    		get { return  m_bvalue ; }
    		set
    		{
    			m_bvalue = value;
    			if (PropertyChanged != null)
    			{
    				PropertyChanged(this, new PropertyChangedEventArgs("BValue"));
    			}
    		}
    	}
    	...
    }
    

    在window的类中声明了一个classA的实例并且完成初始化:
            public classA ClassAInstance;
    
    现在我想在一个DataGrid中生成同样4行3列的结构,使用DataGridTemplateColumn,并且每个单元格使用同一个DataTemplate。
    我在    <Window.Resources> 已经定义好了一个如下的DataTemplate,主要功能是生成一个togglebutton,其checked状态以及显示文字和classB的BValue绑定,bool到string的转换类已经另外写好:
            <DataTemplate x:Key="MeasureTypeTemplate">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <ToggleButton Width="auto" Height="auto" Margin="0" 
                        IsChecked="{Binding Path=BValue, Mode=TwoWay}"
                        Content="{Binding Path=BValue, Mode=OneWay, Converter={StaticResource bts}}" />
                </Grid>
            </DataTemplate>
    

    现在的问题是,我只能在 Datagrid本身的属性内设置 ItemsSource="{Binding ClassAInstance.ClassBInstances}",下一步如何操作才能让每一列的单元格找到正确的ClassB实例进行binding?
    谢谢


    • 已编辑 xdwumin 2012年1月28日 15:50 拼写
    2012年1月28日 15:24

答案

全部回复

  • 如果 ObservableCollection不好用的话,用其他数据结构实现也可以,多谢。
    2012年1月28日 16:18
  • 首先,一个明显错误:

            private ObservableCollection<classBs > m_ ClassBInstances ;
            public ObservableCollection<classBs > ClassBInstances
            { get { return   m_ ClassBInstances ; } }

    然后,你要的是如下这样吗?

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
      <Window.Resources>
        <DataTemplate x:Key="MeasureTypeTemplate">
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <ToggleButton Width="auto" Height="auto" Margin="0" 
                        IsChecked="{Binding Path=BValue, Mode=TwoWay}"
                        Content="{Binding Path=BValue, Mode=OneWay}" />
          </Grid>
        </DataTemplate>
    
      </Window.Resources>
      <Grid>
        <DataGrid ItemsSource="{Binding ClassAInstance.ClassBInstances./}">
          <DataGrid.Columns>
            <DataGridTemplateColumn CellTemplate="{StaticResource MeasureTypeTemplate}"/>
          </DataGrid.Columns>
        </DataGrid>
      </Grid>
    </Window>
    
    

    C#:

      public partial class MainWindow : Window
      {
        public classA ClassAInstance { get; set; }
    
        public MainWindow()
        {
          ClassAInstance = new classA();
          InitializeComponent();
    
          this.DataContext = this;
        }
      }
    
      public class classB : INotifyPropertyChanged
      {
        private bool m_bvalue;
        public bool BValue
        {
          get { return m_bvalue; }
          set
          {
            m_bvalue = value;
            if (PropertyChanged != null)
            {
              PropertyChanged(this, new PropertyChangedEventArgs("BValue"));
            }
          }
        }
        public event PropertyChangedEventHandler PropertyChanged;
      }
    
      public class classA
      {
        public class classBs : ObservableCollection<classB> { }
    
        private ObservableCollection<classBs> m_ClassBInstances;
        public ObservableCollection<classBs> ClassBInstances
        { get { return m_ClassBInstances; } }
    
        public classA()
        {
          m_ClassBInstances = new ObservableCollection<classBs>();
          m_ClassBInstances.Add(new classBs() { 
            new classB() { BValue = true },
            new classB() { BValue = false },
            new classB() { BValue = true },
            new classB() { BValue = false },
            new classB() { BValue = true }
          });
        }
      }
    


    Sincerely,


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    2012年1月30日 3:10
    版主
  • 不好意思,为了简化我把原始代码里的变量名改简单了一些,所以导致了拼写错误。

    我是希望将DataTemplate应用在DataGrid的所有单元格内,也就是说DataGrid的数据源是一个二维数据结构(目前是用两层ObservableCollection嵌套实现的)。

    目前这样的实现只能应用于一维结构,DataTemplate也只能作用在其中某列的单元格上。

    不知道DataGrid能否实现这样的功能。

     

    目前我暂时使用在Grid Layout上靠代码动态创建控件来替代。

    2012年1月30日 5:39
  • 是的,WPF中的ItemsControl所能支持的只能是单独的一维结构,DataGrid所做的也只是嵌套了一个ItemsControl在ItemsControl中,来支持二维。

    所以我的建议是,你也可以自己嵌套ItemsControl作为一个ItemsControl的ItemTemplate来实现。

    或者,看看我的这个例子,实现动态增减DataGrid Column的:http://code.msdn.microsoft.com/windowsdesktop/How-to-add-the-Column-into-2ad31c47 

     


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    • 已标记为答案 xdwumin 2012年1月30日 16:00
    2012年1月30日 7:06
    版主