C# 动态WPF MVVM数据网格行为
如果我有一个名为FXRate对象的对象集合,定义为C# 动态WPF MVVM数据网格行为,c#,wpf,mvvm,datagrid,C#,Wpf,Mvvm,Datagrid,如果我有一个名为FXRate对象的对象集合,定义为 public class FXRate { public string CcyOne { get; set;} public string CcyTwo { get; set;} public decimal Rate { get; set;} } 如果我想在网格中显示,我已经尝试将DataGrid的ItemsSource绑定到ObservableCollection,我可以如下呈现它 Ccy one
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
GBP EUR JPY
GBP 1 1.2 13.1
EUR 1.1 1 5.2
JPY 0.15 0.23 1
等等。。。这允许用户使用可编辑列样式更新速率,并更新基础FXRate对象属性。因此,一旦用户进行了更改,可视更改将直接反映在底层FXRate对象中,然后他们可以保存,保存所有值也很简单
然而,我想要的是呈现如下
Ccy one Ccy two Rate
EUR GBP 1.2
EUR USD 1.5
GBP EUR 0.8
GBP EUR JPY
GBP 1 1.2 13.1
EUR 1.1 1 5.2
JPY 0.15 0.23 1
并使金额单元格仍可编辑并绑定到基础对象,以便用户可以在GUI中进行更改,并使相关的基础FXRate对象相应地更新其金额
有人能想出一种用MVVM实现这一点的方法吗?我最近遇到了同样的问题,尽管是以不同的形式出现的。唯一的方法是创建一个从DataGrid继承的自定义DataGrid。请看这里的答案。它也有一个示例项目供您下载
我希望这会有所帮助。我最终自己编写了一个自定义的解决方案,它似乎很管用,尽管它不是最干净的解决方案,但我非常满意,因为它可以使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; }
}
}