Question

I need a way for viewmodel to instruct XamDataGrid on the view to just reread and repaint its cells with minimal hassle. I do not wish to mess with the source and do some unsustainable workaround with raising its events (the source might change).

To make it more understandable, I have a global static class that holds some visual cues configuration that do not affect data but only they way its represented in the grid (scaling, formatting, etc). The visual action happens in the IValueConverter implementation attached to the field which works just fine. There is a static event which fires when cues change and viewmodels subscribe to it and events fire properly. Now I just need to have the event handler cause the grid to repaint.

Any suggestions?

EDIT: some code, if it helps:

converter:

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 global

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();
            }
        }
    }
}

fields are defined as

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

Solution

if you have a collectionview than call simply Refresh() to it.

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");
    }
  }
}

OTHER TIPS

I was having the same issue, and it turns out even though I had my ViewModel implement INotifyPropertyChanged, I was not implementing INotifyPropertyChanged on the class that the grid rows were binding to in my ObservableCollection (i.e. the YourDataClass in punker76's answer). Once I implemented it on that class as well everything started updating as expected.

I know that you mentioned "I do not wish to mess with the source" so I'm not sure if this solution is acceptable for you, but I thought I would share for others that find this post as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top