代码之家  ›  专栏  ›  技术社区  ›  Partial

WPF DataGrid:DataGridComboxBox项源绑定到集合集合

  •  11
  • Partial  · 技术社区  · 7 年前

    情况:

    我在XAML中创建了一个DataGrid,itemsSource绑定到包含属性的某个类的ObservableCollection。然后在C_中,我创建一个DataGridTextColumn和一个DataGridComboBoxColumn,并将它们绑定到ObservableCollection中对象的属性。我可以将DataGridComboBoxColumn绑定到一个简单集合,但我要做的是将它绑定到一个字符串集合,这样,对于DataGrid中的每一行,ComboBox都有一个不同的字符串集合。我没能做到…

    问题:

    如何绑定DataGridComboxColumn,以便为此类列的每一行使用不同的字符串集合?

    代码示例:

    XAML:

    <Window>
      <!-- ... -->
      WPFToolkit:DataGrid
               x:Name="DG_Operations"
               Margin="10,5,10,5" 
               Height="100" 
               HorizontalAlignment="Stretch" 
               FontWeight="Normal" 
               ItemsSource="{Binding Path=OperationsStats}"
               AlternatingRowBackground="{DynamicResource SpecialColor}" 
               HorizontalScrollBarVisibility="Auto" 
               VerticalScrollBarVisibility="Visible" 
               SelectionMode="Extended"
               CanUserAddRows="False" 
               CanUserDeleteRows="False"
               CanUserResizeRows="True" 
               CanUserSortColumns="True"
               AutoGenerateColumns="False" 
               IsReadOnly="False" 
               IsEnabled="True"
               BorderThickness="1,1,1,1" 
               VerticalAlignment="Stretch"/>
      <!-- ... -->
    </Window>
    

    C:

    public class DataModelStatsOperations
    {
       public ObservableCollection<IStatsOperation> OperationsStats { get; set; }
    }
    
    public interface IStatsOperation
    {
       string Operation { get; set; }
       Collection<string> Data{ get; set; }
    }
    
    public class StatsOperation : IStatsOperation
    {
        public StatsOperation(string operation, Collection<string> data)
        {
            Operation = operation;
            Data = data;
        }
        public string Operation { get; set; }
        public Collection<string> Data{ get; set; }
    }
    
    private ObservableCollection<IStatsOperation> dataOperations_ =
            new ObservableCollection<IStatsOperation>();
    
    //...
     Binding items = new Binding();
     PropertyPath path = new PropertyPath("Operation");
     items.Path = path;
     DG_Operations.Columns.Add(new DataGridTextColumn()
     {
         Header = "Operations",
         Width = 133,
         Binding = items
      });
      DG_Operations.Columns.Add(new DataGridComboBoxColumn()
      {
         Header = "Data",
         Width = 190,
         ItemsSource = /*???*/,
         SelectedValueBinding = new Binding("Data"),
         TextBinding = new Binding("Data")
      });
    dataOperations_.Add(new StatsOperation(CB_Operation.SelectedItem.ToString(),
                                                               dataCollection));
    DG_Operations.DataContext = new DataModelStatsOperations
    {
        OperationsStats = dataOperations_
    };
    //...
    

    任何帮助都将不胜感激!

    笔记:

    好吧,在读了前两个答案后,我注意到了一些事情。我的装订真的不对!现在,我想做的是类似于Andyg提议的事情:

    DG_Operations.Columns.Add(new DataGridComboBoxColumn()
    {
        Header = "Data",
        Width = 190,
        ItemsSource = new Binding("Data"), //notice this here does not work (have a look at the following error)
        SelectedValueBinding = new Binding("Operation"),
        TextBinding = new Binding("Operation")
    });
    

    错误:“无法将类型”System.Windows.Data.Binding“隐式转换为”System.Collections.IEnumerable“。”

    如何将itemsource绑定到数据?

    5 回复  |  直到 13 年前
        1
  •  11
  •   Timothy Khouri    16 年前

    首先,这应该很容易…其次,为什么要在C_中构建(和绑定)列?EEK。

    XAML (我使用常规网格是因为我很懒):

    <ListView Name="MyListView">
        <ListView.View>
            <GridView>
    
                <GridView.Columns>
    
                    <GridViewColumn DisplayMemberBinding="{Binding Operation}" />
    
                    <GridViewColumn>
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox ItemsSource="{Binding Choices}" />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
    
                </GridView.Columns>
    
            </GridView>
        </ListView.View>
    </ListView>
    

    C.* :

    void Window1_Loaded(object sender, RoutedEventArgs e)
    {
        var dahList = new List<StatsOperation>();
    
        dahList.Add(new StatsOperation
        {
            Operation = "Op A",
            Choices = new string[] { "One", "Two", "Three" },
        });
    
        dahList.Add(new StatsOperation
        {
            Operation = "Op B",
            Choices = new string[] { "4", "5", "6" },
        });
    
        this.MyListView.ItemsSource = dahList;
    }
    

    结果:

    WPF grid with dynamic combo box choices http://www.singingeels.com/Articles/Articles/UserImage.aspx?ImageID=b1e3f880-c278-4d2b-bcc2-8ad390591200

        2
  •  4
  •   AndyG    16 年前

    我认为错误在于你是如何装订的。定义列时,绑定与由特定行表示的对象相关。据我所知,每行都有一个statsOperation,所以textbox列被绑定到operation,这就是您的操作方式,而组合框列itemsource应该绑定到一个集合。现在它看起来像是 Collection<Collection<string>> .

    我以前没有在代码隐藏中定义列,所以这里是XAML中的一个示例。我发现ComboBoxColumn有时很复杂,所以我演示了如何使用TemplateColumn或ComboxColumn在列中使用ComboBox。我已经从我自己的代码复制粘贴,所以只需将“dg”替换为“wpftoolkit”即可:

    <dg:DataGrid
          ...
          ...>
          <dg:DataGrid.Columns>
                <dg:DataGridTextColumn Binding="{Binding Operation}" CanUserReorder="True" CanUserResize="True" Header="Operation" />
                <dg:DataGridTemplateColumn CanUserReorder="True" CanUserResize="True" Header="Template Column">
                    <dg:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox ItemsSource="{Binding Data}" SelectedItem="{Binding Operation}" />
                        </DataTemplate>
                    </dg:DataGridTemplateColumn.CellTemplate>
                </dg:DataGridTemplateColumn>
                <dg:DataGridComboBoxColumn
                    Header="ComboBox Column"                                                                                    
                     SelectedValueBinding="{Binding Operation}"                     
                     SelectedItemBinding="{Binding Operation}">
                    <dg:DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="IsSynchronizedWithCurrentItem" Value="False" />
                            <Setter Property="ItemsSource" Value="{Binding Data}" />
                        </Style>
                    </dg:DataGridComboBoxColumn.ElementStyle>
                    <dg:DataGridComboBoxColumn.EditingElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="ItemsSource" Value="{Binding Data}" />
                            <Setter Property="IsDropDownOpen" Value="True" />
                        </Style>
                    </dg:DataGridComboBoxColumn.EditingElementStyle>
                </dg:DataGridComboBoxColumn>
          </dg:DataGrid.Columns>
    
    </dg:DataGrid>
    

    我假设操作是选定的项,数据是要从中选择的项,并且您的数据报绑定到StatsOperation的集合。祝你好运!

        3
  •  2
  •   John Bowen    16 年前

    要修复项源绑定错误,请使用以下表单:

    BindingOperations.SetBinding(new DataGridComboBoxColumn(), DataGridComboBoxColumn.ItemsSourceProperty, new Binding("Data"));
    

    显然,您不能在初始化器中这样做,所以您必须将声明移动一点,但这应该能解决更新中的错误。

        4
  •  1
  •   Anvaka    16 年前

    编辑 对不起,我中午有点慢。)这是一个更新的答案。看起来像文森特·西巴尔的好文章 WPF DataGrid - DataGridComboBoxColumn v1 Intro 回答你的问题。是吗?

        5
  •  0
  •   Charles Prakash Dasari    16 年前

    部分-我认为你所说的有点困惑。您说您需要在每行中收集字符串,这样组合框就可以为不同的行显示不同的字符串。但是,对于显示一组字符串的组合框,您只需要每行的字符串集合,而不需要字符串集合。

    既然您需要每行的字符串集合,那么您可能会认为需要字符串集合。

    我对你问题的理解正确吗?如果是这样,那么您提到的字符串集合是错误的。

    实际上,您需要的是一组语句操作,其中每个语句操作都应该有一组字符串。这正是您在上面的类中所展示的方式。

    为了取得进展,我建议您编辑您的问题,并指出在按照andyg的建议修复绑定之后,您究竟被困在哪里。

    推荐文章