根据布尔值AttachedProperty计算DataGridCells

时间:2015-07-08 09:00:04

标签: c# wpf

我有一个突出显示机制,可根据搜索的模式更改DataGridCell的背景。

<Setter Property="converters:DataGridTextSearch.IsTextMatch">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource SearchValueConverter}">
                        <Binding RelativeSource="{RelativeSource Self}" Path="Content.Text"/>
                        <Binding RelativeSource="{RelativeSource Self}" Path="(converters:DataGridTextSearch.SearchValue)" />
                        <Binding RelativeSource="{RelativeSource Self}" Path="Column.Header" />
                    </MultiBinding>
                </Setter.Value>
</Setter>

触发器定义为:

<Style.Triggers>
                <Trigger Property="converters:DataGridTextSearch.IsTextMatch" Value="True">
                    <Setter Property="Background" Value="LightGray" />
                </Trigger>
</Style.Triggers>

AttachedProperty的代码:

    // Using a DependencyProperty as the backing store for IsTextMatch.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsTextMatchProperty =
        DependencyProperty.RegisterAttached("IsTextMatch", typeof(bool), typeof(DataGridTextSearch), new UIPropertyMetadata(false));

    public static bool GetIsTextMatch(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsTextMatchProperty);
    }

    public static void SetIsTextMatch(DependencyObject obj, bool value)
    {
        obj.SetValue(IsTextMatchProperty, value);
    }

我想计算IsTextMatch为true的所有单元格。我还需要计算行数,一行上可能有很多单元格,所以我必须检测到这一点,但我正在尝试逐步进行。

我试图在我的静态类中添加另一个附加属性,它将计算多少&#34; true&#34;已设定。我从IsTextMatchProperty的PropertyChangedCallback更新了它的值,但它没有用。

这是访问该属性的XAML:

  converters:DataGridTextSearch.CellsCount="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

其中DataGridTextSearch是属性所在的静态类。

还有其他方法吗?如果没有,我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

基本方法是创建一个监督对象,比如Counter,它负责计算突出显示的单元格。

public class Counter : INotifyPropertyChanged
{
    HashSet<DependencyObject> _hash = new HashSet<DependencyObject>();

    public void Add(DependencyObject obj)
    {
        this._hash.Add(obj);
        this.RaisePropertyChanged("Count");
    }

    public void Remove(DependencyObject obj)
    {
        this._hash.Remove(obj);
        this.RaisePropertyChanged("Count");
    }

    public int Count
    {
        get
        {
            return this._hash.Count;
        }
    }

    // INotifyPropertyChanged implementation omitted...
}

将附加的依赖项属性CellCounter添加到您的行为中:

// get/set methods omitted

public static readonly DependencyProperty CounterProperty = DependencyProperty.RegisterAttached(
    "CellsCounter", 
    typeof(Counter), 
    typeof(GridBehavior), 
    new FrameworkPropertyMetadata(GridBehavior.OnCellsCounterPropertyChanged));

private static void OnCellsCounterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var oldCounter = e.OldValue as Counter;
    if (oldCounter != null)
    {
        oldCounter.Remove(d);
    }

    var newCounter = e.NewValue as Counter;
    if (newCounter != null)
    {
        var isSelected = GridBehavior.GetIsSelected(d);
        if (isSelected)
        {
            newCounter.Add(d);
        }
    }
}

将计数器递增/递减的逻辑添加到IsTextMatch属性:

// get/set methods omitted  

public static readonly DependencyProperty IsTextMatchProperty =
        DependencyProperty.RegisterAttached(
            "IsTextMatch", 
            typeof(bool), 
            typeof(GridBehavior), 
            new FrameworkPropertyMetadata(GridBehavior.OnIsTextMatchPropertyChanged));

    private static void OnIsTextMatchPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var counter = d.GetValue(GridBehavior.CellsCounterProperty) as Counter;
        if (counter == null)
        {
            return;
        }

        if ((bool)e.NewValue)
        {
            counter.Add(d);
        }
        else
        {
            counter.Remove(d);
        }
    }

然后在窗口/控件的“资源”部分中定义单个计数器,并在任何位置轮询Count属性。由于计数器的INotifyPropertyChanged性质,所有更改都将自动发送给计数器的消费者。像这样(我使用ListBox而不是DataGrid并且为了简单而没有使用视图模型但是没关系):

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:view="clr-namespace:WpfApplication3">
    <Window.Resources>
        <view:Counter x:Key="CounterKey"/>
    </Window.Resources>
    <StackPanel>
        <ListBox>
            <ListBoxItem view:GridBehavior.IsTextMatch="True"
                         view:GridBehavior.CellsCounter="{StaticResource CounterKey}"
                         Content="a"/>
            <ListBoxItem view:GridBehavior.IsTextMatch="False"
                         view:GridBehavior.CellsCounter="{StaticResource CounterKey}"
                         Content="b"/>
            <ListBoxItem view:GridBehavior.IsTextMatch="False"
                         view:GridBehavior.CellsCounter="{StaticResource CounterKey}"
                         Content="c"/>
            <ListBoxItem view:GridBehavior.IsTextMatch="True"
                         view:GridBehavior.CellsCounter="{StaticResource CounterKey}"
                         Content="d"/>
        </ListBox>

        <TextBlock Text="{Binding Path=Count,Source={StaticResource CounterKey}}"/>
    </StackPanel>
</Window>

N.B。您需要更进一步,仔细增强删除逻辑。例如,现在如果从列表中删除IsTextMatch = true的项目,它不会影响计数器。我相信,你有足够的技巧可以自己做到这一点。