[英]WPF Datagrid binding custom column headers
我試圖弄清楚如何使用MVVM模式將WPF DataGrid的列標題和主數據綁定到數據源。 我正在尋找的結果將是這樣的:
(來源: vallelunga.com )
我在這里成功設置了標題樣式,但我不確定如何綁定標題中的值。 具體來說,復選框的IsChecked屬性,組合框的選定索引和文本框的值。
我以前使用一個簡單的DataTable來填充主網格數據,但是我需要更復雜的東西來保存網格數據和每列的值。 或許我可以完全將它們存儲為單獨的實體。
那么,有沒有人知道如何實現這種約束? 一個限制是列必須是自動生成的,因為我不知道它們在運行時會是什么。 應用程序只是從Excel電子表格加載數據,並且可能存在任意數量的列。
謝謝,Brian
以下是我最終使用MVVM模式進行的操作:
我有兩組用於綁定視圖模型的數據:一組用於實際網格數據,另一組用於列標題。 目前這些屬於兩個屬性:
// INotifyPropertyChanged support not shown for brevity
public DataTable GridData { get; set; }
public BindingList<ImportColumnInfo> ColumnData { get; set; }
使用兩組不同數據的技巧是在網格中。 我已經將DataGrid子類化,並為網格提供了一個名為ColumnSource的附加數據源,作為依賴項屬性。 這是我的視圖模型上的ColumnData綁定的內容。 然后,我將每個自動生成的列的標題設置為ColumnSource數據源中的適當索引數據。 代碼如下:
public class ImporterDataGrid : DataGrid
{
protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
{
base.OnAutoGeneratingColumn(e);
int columnIndex = this.Columns.Count;
var column = new ImporterDataGridColumn();
column.Header = ColumnSource[columnIndex];
column.Binding = new Binding(e.PropertyName) { Mode = BindingMode.OneWay };
e.Column = column;
}
public IList ColumnSource
{
get { return (IList)GetValue(ColumnSourceProperty); }
set { SetValue(ColumnSourceProperty, value); }
}
public static readonly DependencyProperty ColumnSourceProperty = DependencyProperty.Register("ColumnSource", typeof(IList), typeof(ImporterDataGrid), new FrameworkPropertyMetadata(null));
}
我現在可以在我的列的模板化標頭中執行常規數據綁定,這將全部綁定到我的視圖模型的ColumnData屬性中的數據。
更新:我被要求顯示我的網格的XAML。 這是非常基本的,但它是:
<Controls:ImporterDataGrid
AutoGenerateColumns="True" x:Name="previewDataGrid"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible"
IsReadOnly="True"
SelectionMode="Extended"
HeadersVisibility="Column"
ItemsSource="{Binding PreviewData}"
ColumnSource="{Binding PreviewColumnData}"
Style="{StaticResource ImporterDataGridStyle}"
Background="White" CanUserReorderColumns="False" CanUserResizeRows="False"
CanUserSortColumns="False" AlternatingRowBackground="#FFFAFAFA" AllowDrop="True" />
這是ImporterColumnHeaderStyle:
<Style x:Key="ImporterDataGridColumnHeaderStyle" TargetType="{x:Type toolkit:DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type toolkit:DataGridColumnHeader}">
<Grid>
<toolkit:DataGridHeaderBorder Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" IsClickable="{TemplateBinding CanUserSort}" IsHovered="False" IsPressed="False" SortDirection="{TemplateBinding SortDirection}">
<Grid>
<CheckBox Height="16" Margin="6,6,16,0" Name="importCheckBox" IsChecked="{Binding Path=Import}" VerticalAlignment="Top">Import Column</CheckBox>
<StackPanel IsEnabled="{Binding Path=Import}">
<ComboBox Height="24" Margin="6,29,6,0" Name="columnTypeComboBox" VerticalAlignment="Top" SelectedValue="{Binding ColumnType}" ItemsSource="{Binding Source={local:EnumList {x:Type Models:ImportColumnType}}}">
</ComboBox>
<TextBox Height="23" Margin="6,6,6,33" Name="customHeadingTextBox" VerticalAlignment="Bottom" Text="{Binding Path=CustomColumnName}" IsEnabled="{Binding ColumnType, Converter={StaticResource ColumnTypeToBooleanConverter}}" />
</StackPanel>
<TextBlock Height="20" Margin="6,0,6,7" Name="originalHeadingTextBlock" Text="{Binding Path=OriginalColumnName}" VerticalAlignment="Bottom" Foreground="Gray" />
</Grid>
</toolkit:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我絕對是一個WPF / MVVM /數據綁定菜鳥,但最近一直在努力研究這些東西。 到目前為止,我不知道你有什么連接,但首先你要為你的View設置DataContext。 由於您使用的是MVVM,我假設您有一個ViewModel,因此應該是View的DataContext。
即如果你有View創建/擁有你的ViewModel,它可能看起來像這樣:
MyViewModel vm = new MyViewModel();
this.DataContext = vm;
您可以輕松地將CheckBox,ComboBox和TextBox數據綁定到ViewModel中的屬性。 我發現最簡單的方法是使ViewModel繼承自基本的viewmodel類,就像Josh Smith寫的那樣 。 當您希望ViewModel通知GUI任何值的更改時,這將為您提供一種內部調用方法。
假設你有像ImportColumn,LastName和LastNameText這樣的屬性(所有C#屬性,而不是相應調用OnPropertyChanged的字段 ),那么你的XAML看起來像這樣:
<CheckBox IsChecked="{Binding ImportColumn}" />
<ComboBox SelectedItem="{Binding LastName}" />
<TextBox Text="{Binding LastName Text, Mode=TwoWay}" />
我希望這能夠幫到你。 如果沒有,請發表評論,我會盡力做其他事情。
我們在應用中做了類似的事情。
我所做的是派生我自己的列類型(DataGridSearchableBooleanColumn),然后我替換DataGridColumnHeader模板,我在那里放了兩個內容演示者。 第一個我綁定到內容(與默認模板相同),第二個綁定到列。 我為列使用了一個數據模板(我有一些用於不同的搜索類型(text,combo,boolean)。然后我將額外的屬性添加到列中,以便我可以綁定到它們。看看這段代碼是否有意義。
<!--Style for the datagrid column headers, contains a text box for searching-->
<Style
x:Key="columnHeaderStyle"
TargetType="dg:DataGridColumnHeader">
<Setter
Property="Foreground"
Value="#FF000000" />
<Setter
Property="HorizontalContentAlignment"
Value="Left" />
<Setter
Property="VerticalContentAlignment"
Value="Center" />
<Setter
Property="IsTabStop"
Value="False" />
<Setter
Property="Padding"
Value="1,2,1,2" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="dg:DataGridColumnHeader">
<Grid
x:Name="Root">
<dg:DataGridHeaderBorder
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsClickable="{TemplateBinding CanUserSort}"
IsHovered="{TemplateBinding IsMouseOver}"
IsPressed="{TemplateBinding IsPressed}"
SeparatorBrush="{TemplateBinding SeparatorBrush}"
SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
SortDirection="{TemplateBinding SortDirection}">
<Grid
HorizontalAlignment="Stretch"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid.Resources>
<DataTemplate
DataType="{x:Type local:DataGridSearchableBooleanColumn}">
<CheckBox
Margin="0,5,0,0"
IsThreeState="True"
IsChecked="{Binding Path=IsChecked}" />
</DataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition
Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition
Height="19" />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<ContentPresenter
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay, Path=Content}" />
<Path
x:Name="SortIcon"
Fill="#FF444444"
Stretch="Uniform"
HorizontalAlignment="Left"
Margin="4,0,0,0"
VerticalAlignment="Center"
Width="8"
Opacity="0"
RenderTransformOrigin=".5,.5"
Grid.Column="1"
Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z ">
<Path.RenderTransform>
<ScaleTransform
ScaleX=".9"
ScaleY=".9" />
</Path.RenderTransform>
</Path>
<ContentPresenter
x:Name="columnHeaderContentPresenter"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Column}"
Grid.Row="1"
Grid.ColumnSpan="2"
Margin="0,0,0,0" />
</Grid>
</dg:DataGridHeaderBorder>
<Thumb
x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left">
<Thumb.Style>
<Style
TargetType="{x:Type Thumb}">
<Setter
Property="Width"
Value="8" />
<Setter
Property="Background"
Value="Transparent" />
<Setter
Property="Cursor"
Value="SizeWE" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type Thumb}">
<Border
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
<Thumb
x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right">
<Thumb.Style>
<Style
TargetType="{x:Type Thumb}">
<Setter
Property="Width"
Value="8" />
<Setter
Property="Background"
Value="Transparent" />
<Setter
Property="Cursor"
Value="SizeWE" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type Thumb}">
<Border
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Thumb.Style>
</Thumb>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.