【问题标题】:How to Create a Custom DataGrid如何创建自定义数据网格
【发布时间】:2013-08-13 00:16:26
【问题描述】:

所有,在这个回答https://stackoverflow.com/a/18136371/626442 上一个问题中,回答为我的动画不触发的问题提供了一个解决方案。代码是

<DataTemplate x:Key="readOnlyCellUpdatedStyle">
    <TextBlock Text="{Binding KeyIndex, Mode=TwoWay,NotifyOnTargetUpdated=True}">
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Background" Value="White"/>
                <Style.Triggers>
                    <EventTrigger RoutedEvent="Binding.TargetUpdated">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetProperty="Background.Color" 
                                    Duration="0:0:0.3"
                                    From="White" 
                                    To="Red" 
                                    RepeatBehavior="3x" 
                                    AutoReverse="True"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</DataTemplate>

当我通过 ViewModel 更新 KeyIndex 列时,这会触发动画。但是,我只希望 DataGridTextColumn 的单元格的动画在值更新时进行动画处理,但它们也会在 DataGrid 滚动时触发。有人建议我

创建具有您需要的内置功能的派生DataGridTextColumn 可能是更好的选择,因为如果您使用虚拟化,则几乎不可能使用TargetUpdated。但如果你自定义了DataGridTextColumn,你应该可以让它工作。

如何创建自定义/派生的 `DataGridTextColumn(我也可以使用 blend)?

我不知道该怎么做,而且关于这个特定概念的文档很少。

感谢您的宝贵时间。

【问题讨论】:

    标签: c# wpf mvvm user-controls wpfdatagrid


    【解决方案1】:

    当使用VirtualizationMode="Recycling" 时,结果证明与Virtualization 一起工作是相当困难的

    我找到了一种通过派生TextBlock 并附加到绑定对象的PropertyChanged 事件来使其工作的方法。

    当值改变时播放动画,但如果滚动回收的项目不会继续播放动画。

    这是一个非常粗略的示例,但我相信您可以根据需要进行清理和修改。

    文本块:

    public class VirtualizingNotifyTextBlock : TextBlock
    {
        private INotifyPropertyChanged _dataItem;
        private string _propertyName;
    
        public VirtualizingNotifyTextBlock()
            : base()
        {
            this.TargetUpdated += NotifyTextBlock_TargetUpdated;
        }
    
        public static readonly RoutedEvent PropertyChangedEvent = EventManager.RegisterRoutedEvent("PropertyChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(VirtualizingNotifyTextBlock));
        public static readonly DependencyProperty NotifyDurationProperty = DependencyProperty.Register("NotifyDuration", typeof(int), typeof(VirtualizingNotifyTextBlock), new PropertyMetadata(300));
        public static readonly DependencyProperty NotifyRepeatProperty = DependencyProperty.Register("NotifyRepeat", typeof(int), typeof(VirtualizingNotifyTextBlock), new PropertyMetadata(3));
        public static readonly DependencyProperty NotifyColorProperty = DependencyProperty.Register("NotifyColor", typeof(Color), typeof(VirtualizingNotifyTextBlock), new PropertyMetadata(Colors.Red));
    
        public Color NotifyColor
        {
            get { return (Color)GetValue(NotifyColorProperty); }
            set { SetValue(NotifyColorProperty, value); }
        }
    
        public int NotifyDuration
        {
            get { return (int)GetValue(NotifyDurationProperty); }
            set { SetValue(NotifyDurationProperty, value); }
        }
    
        public int NotifyRepeat
        {
            get { return (int)GetValue(NotifyRepeatProperty); }
            set { SetValue(NotifyRepeatProperty, value); }
        }
    
        public INotifyPropertyChanged DataItem
        {
            get { return _dataItem; }
            set
            {
                if (_dataItem != null)
                {
                    Background = new SolidColorBrush(Colors.Transparent);
                    _dataItem.PropertyChanged -= DataItem_PropertyChanged;
                }
                _dataItem = value;
                if (_dataItem != null)
                {
                    _dataItem.PropertyChanged += DataItem_PropertyChanged;
                }
            }
        }
    
        private void NotifyTextBlock_TargetUpdated(object sender, DataTransferEventArgs e)
        {
            var binding = this.GetBindingExpression(VirtualizingNotifyTextBlock.TextProperty);
            if (binding != null)
            {
                _propertyName = binding.ResolvedSourcePropertyName;
                DataItem = binding.DataItem as INotifyPropertyChanged;
            }
        }
    
        private void DataItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == _propertyName)
            {
               var animation = new ColorAnimation(NotifyColor, new Duration(TimeSpan.FromMilliseconds(NotifyDuration)));
               animation.RepeatBehavior = new RepeatBehavior(NotifyRepeat);
               animation.AutoReverse = true;
               Background = new SolidColorBrush(Colors.Transparent);
               Background.BeginAnimation(SolidColorBrush.ColorProperty, animation);
            }
        }
    
    }
    

    Xaml:

    <DataTemplate x:Key="readOnlyCellUpdatedStyle">
        <local:VirtualizingNotifyTextBlock Text="{Binding KeyIndex, NotifyOnTargetUpdated=True}" NotifyColor="Blue" NotifyDuration="250" NotifyRepeat="4" />
    </DataTemplate>
    

    【讨论】:

    • 老兄,非常感谢您花时间回答,非常感谢。我正在通过自己的时间做这个 WPF/MVVM 应用程序来做/学习。我今晚会试试这个,并在适当的时候接受。
    猜你喜欢
    • 2012-03-04
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 2016-12-18
    • 1970-01-01
    相关资源
    最近更新 更多