【问题标题】:Cause xamDataGrid to repaint导致 xamDataGrid 重新绘制
【发布时间】:2011-12-04 10:32:22
【问题描述】:

我需要一种方法让 viewmodel 指示视图上的 XamDataGrid 以最小的麻烦重新读取和重新绘制其单元格。我不想弄乱源并做一些不可持续的解决方法来提高其事件(源可能会改变)。

为了使其更易于理解,我有一个全局静态类,其中包含一些不影响数据的视觉提示配置,但它们仅以它们在网格中的表示方式(缩放、格式等)。视觉动作发生在附加到该字段的IValueConverter 实现中,效果很好。当提示更改并且视图模型订阅它并且事件正确触发时,会触发一个静态事件。现在我只需要让事件处理程序导致网格重新绘制。

有什么建议吗?

编辑:一些代码,如果有帮助的话:

转换器:

public class ScaleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (targetType == typeof(double) || targetType == typeof(double?))
        {
            if (value == null && targetType == typeof(double?)) return null;  // short circuit for null->null, nothing to scale
            if (value is double) return (double)value / DisplayScale.Scale; // shortcut for direct scaling, no need to waste time on conversion
            try
            {
                return System.Convert.ToDouble(value) / DisplayScale.Scale; // for convertible values, eat conversion exception
            }
            catch (Exception) {};
            // if all esle fails return NaN
            return double.NaN; 
        }
        // fallthrough, return null, this should not happen, if it does it means converter is incomplete
        return null;
    }
 ...
}

DisplayScale 全局

public class DisplayScale: NotificationObject
{
    private static KeyValuePair<string, double> _ActiveScaling;
    private static readonly object _lockHandle = new object(); // note: should not contest, but just to be on the safe side
    public static event Action ScalingChanged;

    public static List<KeyValuePair<string, double>> ScaleList { get; private set; }

    static DisplayScale()
    {
        ScaleList = new List<KeyValuePair<string, double>>() 
        { 
            new KeyValuePair<string, double>("No scaling (1's)", 1d),
            new KeyValuePair<string, double>("Thousands (1,000's)", 1000d),
            new KeyValuePair<string, double>("Millions (1,000,000's)", 1000000d),
            new KeyValuePair<string, double>("Billions (1,000,000,000's)", 1000000000d)
         };
        ActiveScaling = ScaleList.First();  // OPTION: could be in per-user config
    }

    public static double Scale { get { return ActiveScaling.Value; } }
    public static KeyValuePair<string, double> ActiveScaling
    {
        get
        {
            lock (_lockHandle) return _ActiveScaling;
        }
        set
        {
            lock (_lockHandle)
            {
                _ActiveScaling = value;
                var eventCall = ScalingChanged;
                if (eventCall != null) eventCall();
            }
        }
    }
}

字段定义为

// resource
<inf:ScaleConverter x:Key="ScaleConverter" />
// field
<igDP:Field Name="Deposit" Converter="{StaticResource ScaleConverter}">

【问题讨论】:

  • 你能发布一些代码吗?你有 cellvaluepresenter 样式吗?
  • 我可以发布代码,但这无关紧要,我只希望网格在源引发 ListChanged 事件时执行它正在执行的任何操作,而实际上不必求助于引发 ListChanged(因为实际上它并没有改变,改变的是值转换器的说明)。
  • 您是否为您的数据类实现了 INotifyPropertyChanged 接口? “存款”属性必须触发 PropertyChanged 事件以触发您的 ValueConverter。如果你有一个 CollectionView 而不是简单地调用 Refresh() 。
  • 数据源实现INotifyPropertyChange,当数据发生变化时,它会按应有的方式刷新。问题是当 PRESENTATION SETTING 更改 (DisplayScale.Scale) 时我也需要它来执行此操作。我找不到办法做到这一点。 ScalingChanged 事件正确触发,如果我将 viewmodel 绑定到它,它会收到通知,但我找不到在数据未更改时导致网格刷新的方法。

标签: c# wpf mvvm prism xamdatagrid


【解决方案1】:

如果你有一个collectionview而不是简单地调用Refresh()。

public class YourViewModel
{
  private ObservableCollection<YourDataClass> yourColl;

  public void YourViewModel()
  {
    yourColl = new ObservableCollection<YourDataClass>();
    YourCollectionView = CollectionViewSource.GetDefaultView(yourColl);
    DisplayScale.ScalingChanged += () => YourCollectionView.Refresh();
  }

  var ICollectionView yourCollView;
  public ICollectionView YourCollectionView
  {
    get { yourCollView; }
    set {
      yourCollView = value;
      RaisePropertyChanged("YourCollectionView");
    }
  }
}

【讨论】:

  • 嗯,这可能确实有效,前提是 Refresh() 不会提醒其他观察者注意数据源。我会尝试一下。谢谢
【解决方案2】:

我有 the same issue,结果即使我的 ViewModel 实现了 INotifyPropertyChanged,我也没有在我的 ObservableCollection 中网格行绑定到的类上实现 INotifyPropertyChanged(即 YourDataClass em> 在 punker76 的回答中)。一旦我在那个类上实现了它,一切都开始按预期更新。

我知道你提到“我不想弄乱源”,所以我不确定这个解决方案是否适合你,但我想我也会分享给其他发现这篇文章的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多