65.9K
CodeProject 正在变化。 阅读更多。
Home

使用附加属性在 ViewModel 中进行访问控制

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.12/5 (12投票s)

2011 年 9 月 11 日

CPOL

2分钟阅读

viewsIcon

64157

downloadIcon

1396

本文展示了如何使用附加属性在 ViewModel 中访问控件。

引言

在 MVVM 中,有时我们需要在 ViewModel 中访问特定的控件。例如,如果我想将 IEnumerable 绑定到 DataGrid,因为我无法在运行时确定字段。现在,如果我绑定 IEnumerable<dynamic> 并设置 AutogeneratedColumns = trueDataGrid 仍然不会显示记录,因为每一行都作为具有动态属性表示字段的 "ExpandoObject" 返回。在这种情况下,我必须动态添加列。为此,我需要 DataGrid 控件。现在,要获取 ViewModel 中的 dataGrid 控件,我们可以使用附加属性。让我们尝试一下。

背景

为了更好地理解本文,我建议阅读关于附加属性的内容。

Using the Code

首先,在 ViewModel 中为控件定义附加属性。

Public static readonly DependecyProperty DataGridProperty = _  
 DependencyProperty.RegisterAttached("DataGrid", typeof(DataGrid),  
 typeof(MainWindowViewModel),  
 New FrameworkPropertyMetadata(OnDataGridChanged));  
  
 public static void SetDataGrid(DependencyObject element, DataGrid value)  
 {  
 element.SetValue(DataGridProperty, value);  
 }  
  
 public static DataGrid GetDataGrid(DependencyObject element)  
 {  
 return (DataGrid)element.GetValue(DataGridProperty);  
 }

name 属性分配给控件。现在我们需要将控件与此附加属性绑定。

<Window x:Class="AccessControlsInViewModel.MainWindow"  
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
 xmlns:local="clr-namespace:AccessControlsInViewModel"  
 Title="Access Controls In ViewModel" Height="350" Width="525">  
 <DockPanel>  
 <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Margin="0,0,0,25">  
 <Button Content="Add Columns" Command="{Binding AddCommand}" />  
 </StackPanel>  
 <DataGrid Name="accessGrid" ItemsSource="{Binding ListOfPerson}"  
 local:MainWindowViewModel.DataGrid="{Binding ElementName=accessGrid}" />  
 </DockPanel>  
 </Window>

这里我使用 ElementName 绑定将控件与附加属性绑定。

使用附加属性的原因是我们需要将整个控件与属性绑定,并且没有内置属性可用于执行此操作。

然后定义一个 static 变量来存储控件,并在附加属性更改事件上分配其值。

// DataGrid Instance in the viewModel  
 private static DataGrid dataGrid = null;  
  
 // DataGrid Property changed event  
 public static void OnDataGridChanged  
 (DependencyObject obj, DependencyPropertyChangedEventArgs args)  
 {  
 dataGrid = obj as DataGrid;  
 }

现在我们已经在 ViewModel 中拥有了可用的控件。因此,我们可以实现与在代码隐藏文件中所能做的一切相同的功能。

对于 DataGrid 示例,在添加 button 的命令上,我们可以像这样添加列

 private static void AddDynamicColumnsToDataGrid()  
 {  
 IEnumerable<IDictionary<string, object>>  
 rows = dataGrid.ItemsSource.OfType<IDictionary<string, object>>();  
 IEnumerable<string> columns = rows.SelectMany  
 (d => d.Keys).Distinct(StringComparer.OrdinalIgnoreCase);  
 foreach (string text in columns)  
 {  
 // now set up a column and binding for each property  
 var column = new DataGridTextColumn  
 {  
 Header = text,  
 Binding = new Binding(text)  
 };  
  
 dataGrid.Columns.Add(column);  
 }  
 }

关注点

为了解决这个问题,我同时在 Button 上添加了单击事件和命令,并且这个技巧对我来说真的有效。但是由于我正在使用 MVVM,我需要在 ViewModel 中执行此操作,并且我找到了这个解决方案。

使用附加属性在 ViewModel 中访问控件 - CodeProject - 代码之家
© . All rights reserved.