【问题标题】:How to bind a GridColumn to the index value of an ObservableCollection?如何将 GridColumn 绑定到 ObservableCollection 的索引值?
【发布时间】:2018-03-22 17:24:12
【问题描述】:

我有一个 DevExpress GridControl,它使用 Student 类型的 ObservableCollection 作为其 ItemsSource。

我的 GridControl 有四列

Name
ID
Favorite Subject
GPA

姓名、最喜欢的科目和 GPA 是学生的属性,因此它们具有准确的约束力。

问题是,我不想拥有学生 ID 的属性。我想将 ID 设置为 1 + 托管 GridControl 的学生 ObservableCollection 中学生实例的索引。

所以如果我有三个学生,ID 列将显示为

1
2
3

我怀疑我的视图模型中需要一个 Ints 类型的 ObservableCollection,但我无法为 ID 列使用不同的 ItemsSource。我只能引用 GridControl 的 Parent ItemsSource。由于 ItemsSource 是 Student 类型的 ObservableCollection 并且 ID 不是 Student 的属性,因此我似乎无法将该列设置为适当的值(如上所述)。

<dxg:GridControl Style="{StaticResource StudentsGridControl}"
                                 ItemsSource="{Binding StudentsCollection}" SelectedItem="{Binding SelectedStudent}">
                    <dxg:GridControl.Columns>
                        <dxg:GridColumn Width="200" HorizontalHeaderContentAlignment="Center" Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}">
                            <dxg:GridColumn.HeaderTemplate>
                                <DataTemplate>
                                    <TextBlock Text="Student Name" Style="{StaticResource BaseColumnHeaderStyle}"/>
                                </DataTemplate>
                            </dxg:GridColumn.HeaderTemplate>
                            <dxg:GridColumn.HeaderStyle>
                                <Style TargetType="Control">
                                    <Setter Property="Background" Value="#22322"/>
                                </Style>
                            </dxg:GridColumn.HeaderStyle>
                        </dxg:GridColumn>
                        <dxg:GridColumn Width="50" HorizontalHeaderContentAlignment="Center" 
Binding= // This is the ID Column     
                       <dxg:GridColumn.HeaderTemplate>
                                <DataTemplate>
                                    <TextBlock Text="ID" Style="{StaticResource BaseColumnHeaderStyle}"/>
                                </DataTemplate>
                            </dxg:GridColumn.HeaderTemplate>
                            <dxg:GridColumn.HeaderStyle>
                                <Style TargetType="Control">
                                    <Setter Property="Background" Value="#123453"/>
                                </Style>
                            </dxg:GridColumn.HeaderStyle>
                        </dxg:GridColumn>
                        <dxg:GridColumn Width="230" HorizontalHeaderContentAlignment="Center" Binding="{Binding FavoriteSubject, UpdateSourceTrigger=PropertyChanged}">
                            <dxg:GridColumn.HeaderTemplate>
                                <DataTemplate>
                                    <TextBlock Text="Favorite Subject" Style="{StaticResource BaseColumnHeaderStyle}"/>
                                </DataTemplate>
                            </dxg:GridColumn.HeaderTemplate>
                            <dxg:GridColumn.HeaderStyle>
                                <Style TargetType="Control">
                                    <Setter Property="Background" Value="#52648F"/>
                                </Style>
                            </dxg:GridColumn.HeaderStyle>
                        </dxg:GridColumn>
                        <dxg:GridColumn Width="50" HorizontalHeaderContentAlignment="Center" Binding="{Binding GPA, UpdateSourceTrigger=PropertyChanged}">
                            <dxg:GridColumn.HeaderTemplate>
                                <DataTemplate>
                                    <TextBlock Text="GPA"Style="{StaticResource BaseColumnHeaderStyle}"/>
                                </DataTemplate>
                            </dxg:GridColumn.HeaderTemplate>
                            <dxg:GridColumn.HeaderStyle>
                                <Style TargetType="Control">
                                    <Setter Property="Background" Value="#52658F"/>
                                </Style>
                            </dxg:GridColumn.HeaderStyle>
                        </dxg:GridColumn>
                    </dxg:GridControl.Columns>
                    <dxg:GridControl.View>
                        <dxg:TableView Style="{StaticResource StudensTable}"/>
                    </dxg:GridControl.View>
                   </dxg:GridControl>

【问题讨论】:

  • 你希望用ID字段做什么?由于它与学生无关,因此每次删除或添加学生到列表时,ID 字段都可能不同。事实上,您是否希望将其与学生联系起来?
  • 基本上仅供参考。它用于更直观的控件,为了简洁起见,我宁愿使用 ID 而不是名称。我不想将此属性保留给 Student 的原因是因为无法在此特定视图中从集合中删除项目,我希望在重新打开此特定窗口时重置它们。

标签: c# wpf xaml devexpress


【解决方案1】:

只需为您的 Student 类创建一个 StudentViewModel,不要忘记将您的 StudentsCollection 更改为 ObservableCollection&lt;StudentViewModel&gt;。 ViewModel 用于避免将模型直接绑定到视图,它还允许您在不影响模型的情况下声明其他属性,如本例中的 ID

让我们假设这是您的学生课程:

public class Student
{
    public string Name { get; set; }
    public string FavoriteSubject { get; set; }
    public string GPA { get; set; }
}

您的 StudentViewModel 可能是这样的:

public class StudentViewModel
{
    private Student _student;

    public StudentViewModel(Student student, int id)
    {
        _student = student;
        ID = id;
    }

    public int ID { get; set; }

    public string Name
    {
        get { return _student.Name; }
        set { _student.Name = value; }
    }

    public string FavoriteSubject
    {
        get { return _student.FavoriteSubject; }
        set { _student.FavoriteSubject = value; }
    }

    public string GPA
    {
        get { return _student.GPA; }
        set { _student.GPA = value; }
    }
}

【讨论】:

    【解决方案2】:

    作为解决方案之一,您可以使用MultiBinding 并在MultiValueConverter 中查找索引或您想要的任何内容:

    public class MValConv : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                try
                {
                    if(values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue)
                    return -1;
                    if (values.Length == 2 && values[0] is ObservableCollection<Student> ocol && values[1] is Student st)
                    {
                        return (ocol.IndexOf(st) + 1).ToString();
                    }
                }
                catch (Exception)
                {
                }            
                return Binding.DoNothing;
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException("one way only");
            }
        }
    
    <Window.Resources>
        <local:MValConv x:Key="MValCnv"/>
    </Window.Resources>
    
    <dxg:GridColumn.Binding>
        <MultiBinding Converter="{StaticResource MValCnv}">
            <Binding Path="DataContext.StudentsCollection" RelativeSource="{RelativeSource AncestorType=dxg:GridControl}"/>
            <Binding/>
        </MultiBinding>
    </dxg:GridColumn.Binding>  
    

    嗯,如果是 DevExpress 的错误,那么你可以尝试使用常规绑定 + ValueConverter 与集合的依赖属性。

    【讨论】:

    • 我明白了,但问题是 values[] 以 DependencyProperty.UnsetValue 的形式出现
    • 你试过不绑定收藏吗,只有&lt;Binding/&gt;成为Student吗
    • 我看到 DevExpress 有一个“功能”: 此行为是 13.2 版的已知限制。不可能将列绑定到除 RowData.Row.PropertyName 或 RowData.Data.PropertyName 以外的外部源(或者只是没有前缀的 PropertyName)。 Multibinding giving a DependencyProperty.UnsetValue
    猜你喜欢
    • 1970-01-01
    • 2014-01-12
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2011-04-10
    • 2014-08-23
    • 1970-01-01
    相关资源
    最近更新 更多