1

如果我有一个名为 FXrate 对象的对象集合,定义为

public class FXRate
{
    public string CcyOne { get; set;}
    public string CcyTwo { get; set;}
    public decimal Rate { get; set;}
}

我想在网格中显示,我尝试将 DataGrid 的 ItemsSource 绑定到 ObservableCollection,我可以按如下方式呈现它

Ccy one         Ccy two         Rate 
EUR             GBP             1.2 
EUR             USD             1.5 
GBP             EUR             0.8

等等...这让用户(使用可编辑的列样式)更新速率,这会更新底层的 FXRate 对象属性。因此,一旦用户进行更改,视觉更改直接反映在底层 FXRate 对象中,然后他们可以保存并且保存所有值很简单。

但是我想要的是如下渲染它

    GBP      EUR      JPY
GBP   1        1.2      13.1
EUR   1.1      1        5.2
JPY   0.15     0.23     1

并且让数量单元仍然可编辑并绑定到基础对象,因此用户可以在 GUI 中进行更改并让相关的基础 FXRate 对象相应地更新其数量。

谁能想到用 MVVM 实现这一目标的方法?

4

2 回答 2

0

我最近遇到了同样的问题,尽管形式不同。这样做的唯一方法是创建一个自定义DataGrid继承自DataGrid. 请参阅如何在运行时使用 MVVM 将 List<object> 绑定到 DataGrid以及那里的答案。它还有一个示例项目供您下载...

我希望这有帮助。

于 2013-11-06T17:33:54.807 回答
0

我最终自己编写了一些似乎可行的自定义解决方案,尽管它不是最干净的解决方案,但我对它感到满意,因为它将数据保存在 ViewModels 中并且更新易于跟踪。最大的障碍是从 viewModel 访问样式,但在下面已经这样做了。如果你有兴趣看看我是如何解决这个问题的,请看一下。

在 XAML 中

<ContentControl Content="{Binding CorrelationGrid}" Grid.Row="0" VerticalAlignment="Top" Background="Transparent" HorizontalAlignment="Left" />

在主视图模型中

 private ItemsControl _correlationGrid;
public ItemsControl CorrelationGrid
{
    get { return _correlationGrid; }
    set 
    { 
        _correlationGrid = value;
        RaisePropertyChanged("CorrelationGrid");
    }
}

private void RefreshCorrelationGrid()
{
    var resourceDictionary = new ResourceDictionary { Source = new Uri("/WMA.GUI;component/Styles.xaml", UriKind.RelativeOrAbsolute) };

    var grid = new DataGrid
                   {
                       HeadersVisibility = DataGridHeadersVisibility.All,
                       GridLinesVisibility = DataGridGridLinesVisibility.All,
                       Background = Brushes.Transparent,
                       CanUserAddRows = false,
                       CanUserResizeColumns = false,
                       CanUserReorderColumns = false,
                       CanUserSortColumns = false,
                       CanUserResizeRows = false,
                       AutoGenerateColumns = false,
                       HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden,
                       BorderThickness = new Thickness(0),
                       RowHeaderTemplate = resourceDictionary["DataGridRowHeaderTemplate"] as DataTemplate,
                       RowHeaderStyle = resourceDictionary["DataGridRowHeader"] as Style,
                       RowHeaderWidth = 35,
                       SelectionMode = DataGridSelectionMode.Single,
                       RowHeight = 21,
                       VerticalContentAlignment = VerticalAlignment.Center
                   };

    var tableRows = new ObservableCollection<CorrelationTableRowViewModel>();
    var index = 0;

    foreach (var ccy in _availableCcys.OrderBy(c => c).Where(c => !c.ToUpper().Equals("USD")))
    {
        var row = new CorrelationTableRowViewModel(ccy);
        tableRows.Add(row);

        grid.Columns.Add(GetCorrelationColumn(row, index, resourceDictionary));

        foreach (var ccyMapping in _availableCcys.OrderBy(c => c).Where(c => !c.ToUpper().Equals("USD")))
        {
            var correlation = _fxCorrelations.FirstOrDefault(f => (f.CcyOne == row.Ccy && f.CcyTwo == ccyMapping) || f.CcyTwo == row.Ccy && f.CcyOne == ccyMapping);

            // If for some reason we don't have a mapped correlation for this ccy pairing, create it now
            if (correlation == null)
            {
                correlation = new FxCorrelation(row.Ccy, ccyMapping, 0.0m);
                _fxCorrelations.Add(correlation);
            }

            row.Correlations.Add(correlation);
        }

        index++;
    }

    grid.ItemsSource = tableRows;
    grid.Loaded += GridLoaded;
    CorrelationGrid = grid;
}

private DataGridTextColumn GetCorrelationColumn(CorrelationTableRowViewModel row, int index, ResourceDictionary resourceDictionary)
{
    // This gives us a setter we can use to assign background colours to correlation cells that have been modified
    var highlightStyleSetter = new Setter
    {
        Property = Control.BackgroundProperty,
        Value = resourceDictionary["GridModifiedCellBackground"] as Brush
    };

    var highlightStyle = new Style(typeof(DataGridCell));
    var trigger = new DataTrigger { Binding = new Binding("Correlations[" + index + "].Modified"), Value = true };
    trigger.Setters.Add(highlightStyleSetter);
    highlightStyle.Triggers.Add(trigger);

    return new DataGridTextColumn
        {
            Header = row.Ccy, 
            Width = new DataGridLength(50),
            Binding = new Binding("Correlations[" + index + "].Amount") { Mode = BindingMode.TwoWay, StringFormat = "0.####"},
            HeaderStyle = resourceDictionary["DataGridColumnHeader"] as Style,
            ElementStyle = resourceDictionary["DataGridTextStyle"] as Style,
            CellStyle = highlightStyle
        };
}

private static void GridLoaded(object sender, RoutedEventArgs e)
{
    var dep = sender as DependencyObject;

    while (!(dep is Button))
    {
        if (dep == null) return;
        if (VisualTreeHelper.GetChildrenCount(dep) == 0) return;
        dep = VisualTreeHelper.GetChild(dep, 0);
    }

    var resourceDictionary = new ResourceDictionary { Source = new Uri("/WMA.GUI;component/Styles.xaml", UriKind.RelativeOrAbsolute) };

    var button = dep as Button;
    button.Template = resourceDictionary["SelectAllButtonTemplate"] as ControlTemplate;
}

以及我的网格行数据的 ViewModel

public class CorrelationTableRowViewModel : ViewModelBase
    {
        private string _ccy;
        private readonly IList<FxCorrelation> _correlations;

        public CorrelationTableRowViewModel(string ccy)
        {
            _ccy = ccy;
            _correlations = new List<FxCorrelation>();
        }

        public string Ccy
        {
            get { return _ccy; }
            set
            {
                _ccy = value;
                RaisePropertyChanged("Ccy");
            }
        }

        public IList<FxCorrelation>  Correlations
        {
            get { return _correlations; }
        }
    }
于 2013-11-08T10:57:48.443 回答