将数据表列绑定到存储在列表中的类属性

时间:2014-10-09 17:03:15

标签: c# wpf xaml

很抱歉这个令人困惑的标题。我有一个动态生成的网格绑定到数据表。单击一列时,我创建了一个新类,用于存储过滤所需的信息(不同的项目列表,列索引,标题颜色等。我将它们存储在List中。我有一个模板标题列,用于创建标签和按钮在标题顶部的堆栈面板中。我使用代码隐藏来获取列索引并在视图模型中设置属性。

一切都很好用,除了我不太确定如何将标签的背景颜色绑定到listIndex属性=实际列索引的List。我知道这可能仍然相当令人困惑,这里是代码:

Xaml模板列:

<local:UserControlViewBase.Resources>
    <Style TargetType="DataGridColumnHeader">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border BorderBrush="Black" BorderThickness="1">
                        <StackPanel Orientation="Horizontal" Width="150">
                            <Label Width="90" Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridColumnHeader}},Path=Column.Header}"
                                Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            <Button Content="Ok" Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</local:UserControlViewBase.Resources>

Code Behind(Xaml.cs文件):

private void TestListView_MouseUp(object sender, RoutedEventArgs e)
    {
        GenericQueueViewModel temp = (GenericQueueViewModel)this.DataContext;
        DataGridColumnHeader oTest;
        Button oBtn;
        int x = 0;
        if (!(e.OriginalSource.GetType() == typeof(Button)))
        {
            return;               
        }
        else
        {
            oBtn = (Button)e.OriginalSource;
            DataGrid oTst = (DataGrid)e.Source;
            DataGridColumn oCol = (DataGridColumn)oTst.Columns.FirstOrDefault(y => y.Header == oBtn.DataContext);
            int index = oTst.Columns.IndexOf(oCol);

            DataGridColumnHeader colHeader = GetHeader(oCol, oTst);


            double newX = temp.OldScrollValue;               
            for (int i = 0; i < index; i++)
            {
                newX += oTst.Columns[i].ActualWidth;
            }

            Thickness oThick = new Thickness(newX, -122, 0, 0);
            temp.FilterWindowMargin = oThick;
            x = (sender as DataGrid).Columns.IndexOf(oCol);
            colHeader.Background = System.Windows.Media.Brushes.LightSkyBlue;
        }

        temp.UpdateFilterList(x);
    }

ViewModel类:

[SerializableAttribute]
    public class FilterList
    {
        private int _columnIndex;

        public int ColumnIndex
        {
            get { return _columnIndex; }
            set 
            { 
                _columnIndex = value;
            }
        }

        private System.Windows.Media.Brush _headerColor;

        public System.Windows.Media.Brush HeaderColor
        {
            get { return _headerColor; }
            set 
            { 
                _headerColor = value; 
            }
        }


        private Nullable<bool> _selectAll;

        public Nullable<bool> SelectAll
        {
            get { return _selectAll; }
            set 
            { 
                _selectAll = value; 
            }
        }


        private List<CheckedListItem<DistinctColumnData>> _filterItems;

        public List<CheckedListItem<DistinctColumnData>> FilterItems
        {
            get { return _filterItems; }
            set 
            {
                LastFilterItems = _filterItems;
                _filterItems = value;
            }
        }

        private List<CheckedListItem<DistinctColumnData>> _viewableFilterItems;

        public List<CheckedListItem<DistinctColumnData>> ViewableFilterItems
        {
            get { return _viewableFilterItems; }
            set 
            { 
                _viewableFilterItems = value; 
            }
        }


        private List<CheckedListItem<DistinctColumnData>> _lastFilterItems;

        public List<CheckedListItem<DistinctColumnData>> LastFilterItems
        {
            get { return _lastFilterItems; }
            set { _lastFilterItems = value; }
        }

        private bool _isFiltered;

        public bool IsFiltered
        {
            get { return _isFiltered; }
            set 
            { 
                _isFiltered = value; 
            }
        }


        private bool _isFilterable;

        public bool IsFilterable
        {
            get { return _isFilterable; }

            set 
            { 
                _isFilterable = value; 
            }
        }


        public FilterList()
            : this(-1) { }

        public FilterList(int columnIndex)
            : this(columnIndex, new List<CheckedListItem<DistinctColumnData>>()) { }

        public FilterList(List<CheckedListItem<DistinctColumnData>> filterList)
            : this(-1, filterList) { }

        public FilterList(int columnIndex, List<CheckedListItem<DistinctColumnData>> filterList)
            : this(columnIndex, filterList, false) { }

        public FilterList(int columnIndex, List<CheckedListItem<DistinctColumnData>> filterList, bool isFilterable)
        {
            FilterItems = filterList;
            ColumnIndex = columnIndex;
            IsFilterable = isFilterable;
            HeaderColor = System.Windows.Media.Brushes.Transparent;
        }
    }

ViewModel列表:

private List<FilterList> _filterColumns;

    public List<FilterList> FilterColumns
    {
        get { return _filterColumns; }
        set 
        { 
            _filterColumns = value;
            OnPropertyChanged(() => FilterColumns);
        }
    }

基本上,我需要将xaml DataGridColumnHeader模板标签背景以某种方式绑定到List中的FilterList,其中FilterList.columnIndex = DataGrid列被单击。代码隐藏中的代码行(xaml.cs):

DataGridColumnHeader colHeader = GetHeader(oCol, oTst);

确实得到了一个标题对象(GetHeader是我在另一篇文章中找到的方法)。但它似乎并没有做任何事情。如果我从column0获取标题,并将其颜色设置为LightBlue,然后再次单击column0,则header.background = null ...即使我单步执行它也会更改为十六进制值..下一次它抓住标题,background = null ......

这是一个通用表,需要能够绑定到任何发送的表,包含任意数量的列/行,并提供过滤功能。过滤器功能已经工作,我只是无法弄清楚如何更改标题的背景颜色(技术上,标题顶部的标签),以便他们可以直观地看到哪些列被过滤。

1 个答案:

答案 0 :(得分:0)

我想我明白了。必须使用转换器。改变代码如下,添加转换器:

<local:UserControlViewBase.Resources>
    <Converters:BGConverter x:Key="BackgroundConverter"/>
    <Style TargetType="DataGridColumnHeader">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border BorderBrush="Black" BorderThickness="1" Width="150">
                        <StackPanel x:Name="testtest" Orientation="Horizontal"
                            Background="{Binding Converter={StaticResource BackgroundConverter}, ConverterParameter={x:Reference TestListView}}">                                        
                            <Label Width="90" Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridColumnHeader}},Path=Column.Header}"
                                Padding="12,0,12,0" HorizontalAlignment="Center" VerticalAlignment="Center" />
                            <Button Content="Ok" Padding="12,0,12,0"  HorizontalAlignment="Right" VerticalAlignment="Center" Margin="10,0,0,0"/>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>        
</local:UserControlViewBase.Resources>

现在,从转换器,我可以添加逻辑。这使用Singleton,所以如果你不是粉丝,你需要找到另一种方法来获取你的VM。它在前几次将VM传递给转换器,所以我将它存储在我的mainviewmodel中,然后在它开始传入列时使用它:

 public class BGConverter : IValueConverter
{
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        GenericQueueViewModel oQueue;
        System.Windows.Media.Brush returnBrush;

        DataGrid oGrid = (DataGrid)parameter;
        if (value == null)
        {
            returnBrush = System.Windows.Media.Brushes.Transparent;
        }
        else if (oGrid == null)
        {
            returnBrush = System.Windows.Media.Brushes.Transparent;
        }
        else if (value.GetType() == typeof(GenericQueueViewModel))
        {
            MainViewModel.Instance.GenericVM = (GenericQueueViewModel)value;
            returnBrush = System.Windows.Media.Brushes.Transparent;
        }

        else
        {
            oQueue = MainViewModel.Instance.GenericVM;
            DataGridColumn oCol = oGrid.Columns.FirstOrDefault(y => y.Header == value);
            int colIndex = oGrid.Columns.IndexOf(oCol);
            string colName = (string)value;

            var fList = oQueue.FilterColumns.FirstOrDefault(y => y.ColumnIndex == colIndex && y.IsFiltered == true);
            if (fList == null)
            {
                returnBrush = System.Windows.Media.Brushes.Transparent;
            }
            else
            {
                returnBrush = System.Windows.Media.Brushes.Red;
            }
        }

        return returnBrush;
    }
}