-
May 23rd, 2017, 01:30 PM
#1
Extending DataGrid columns
I'm kind of new to WPF. I'm trying to write classes to extend DataGrid columns to make my life easier.
Here's a sample mainwindow.xaml, containing two DataGrids. The one on top uses the new class, using the syntax that I want, but it doesn't work. The one on the bottom uses the old class, and it works, but the syntax is too complicated.
Code:
<UserControl x:Class="DataGridTestBed.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridTestBed"
d:DataContext="{d:DesignInstance local:MainWindowViewModel, IsDesignTimeCreatable=True}"
mc:Ignorable="d">
<StackPanel>
<DataGrid
ItemsSource="{Binding Items}"
AutoGenerateColumns="False"
>
<DataGrid.Columns >
<local:TestDataGridTextColumn
FieldConfig="{Binding FirstNameConfig}"
Binding="{Binding FirstName}"
/>
<local:TestDataGridTextColumn
FieldConfig="{Binding MiddleNameConfig}"
Binding="{Binding MiddleName}"
/>
<local:TestDataGridTextColumn
FieldConfig="{Binding LastNameConfig}"
Binding="{Binding LastName}"
/>
</DataGrid.Columns>
</DataGrid>
<DataGrid
ItemsSource="{Binding Items}"
AutoGenerateColumns="False"
>
<DataGrid.Resources>
<local:BindingProxy x:Key="Proxy" Data="{Binding}"/>
</DataGrid.Resources>
<DataGrid.Columns >
<DataGridTextColumn Binding="{Binding FirstName}" Header="{Binding Data.FirstNameHeader, Source={StaticResource Proxy}}"
Visibility="{Binding Data.FirstNameVisibility, Source={StaticResource Proxy}}"/>
<DataGridTextColumn Binding="{Binding MiddleName}" Header="{Binding Data.MiddleNameHeader, Source={StaticResource Proxy}}"
Visibility="{Binding Data.MiddleNameVisibility, Source={StaticResource Proxy}}"/>
<DataGridTextColumn Binding="{Binding LastName}" Header="{Binding Data.LastNameHeader, Source={StaticResource Proxy}}"
Visibility="{Binding Data.LastNameVisibility, Source={StaticResource Proxy}}"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</UserControl>
The constructor for my main window view model:
Code:
public MainWindowViewModel()
{
FirstNameConfig = new FieldConfig { Header = "First Name", Visible = true };
MiddleNameConfig = new FieldConfig { Header = "Middle Name", Visible = false };
LastNameConfig = new FieldConfig { Header = "Last Name", Visible = true };
Items = new ObservableCollection<TestItem>
{
new TestItem() {FirstName = "Rocket", MiddleName = "J.", LastName="Squirrel"},
new TestItem() {FirstName = "Homer", MiddleName = "J.", LastName="Simpson"}
};
}
TestDataGridTextColumn.xaml:
Code:
<DataGridTextColumn x:Class="DataGridTestBed.TestDataGridTextColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Visibility="{Binding TheVisibility}"
Header="{Binding TheHeader}"
>
</DataGridTextColumn>
TestDataGridTextColumn.xaml.cs:
Code:
using System.Windows;
namespace DataGridTestBed
{
public partial class TestDataGridTextColumn
{
public static readonly DependencyProperty FieldConfigProperty = DependencyProperty.Register(
"FieldConfig",
typeof(FieldConfig), typeof(TestDataGridTextColumn));
public FieldConfig FieldConfig
{
get { return GetValue(FieldConfigProperty) as FieldConfig; }
set { SetValue(FieldConfigProperty, value); }
}
public Visibility TheVisibility => FieldConfig.Visibility;
public string TheHeader => FieldConfig.Header;
public TestDataGridTextColumn()
{
InitializeComponent();
}
}
}
These data errors are occurring:
Code:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=TheVisibility; DataItem=null; target element is 'TestDataGridTextColumn' (HashCode=28633162); target property is 'Visibility' (type 'Visibility')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=TheHeader; DataItem=null; target element is 'TestDataGridTextColumn' (HashCode=28633162); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FirstNameConfig; DataItem=null; target element is 'TestDataGridTextColumn' (HashCode=28633162); target property is 'FieldConfig' (type 'FieldConfig')
And also, my "FieldConfig" setter isn't getting hit at all.
How can I fix this, without overcomplicating the main window XAML? I'll extend the DataGrid class itself if I have to, but I really want to keep the main window XAML for the top DataGrid as close to the way it looks now as possible.
-
May 24th, 2017, 11:11 AM
#2
Re: Extending DataGrid columns
I updated the project in a major way, and it sort of works, but I'm not happy with it yet.
My new main window:
Code:
<UserControl x:Class="DataGridTestBed.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridTestBed"
d:DataContext="{d:DesignInstance local:MainWindowViewModel, IsDesignTimeCreatable=True}"
mc:Ignorable="d">
<StackPanel>
<local:TestDataGrid
ItemsSource="{Binding Items}"
AutoGenerateColumns="False"
>
<local:TestDataGrid.Columns >
<local:TestDataGridColumn
FieldConfig="{Binding Data.FirstNameConfig, Source={StaticResource Proxy}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}"></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</local:TestDataGridColumn >
<local:TestDataGridColumn
FieldConfig="{Binding Data.MiddleNameConfig, Source={StaticResource Proxy}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding MiddleName}"></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</local:TestDataGridColumn >
<local:TestDataGridColumn
FieldConfig="{Binding Data.LastNameConfig, Source={StaticResource Proxy}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding LastName}"></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</local:TestDataGridColumn >
</local:TestDataGrid.Columns>
</local:TestDataGrid>
</StackPanel>
</UserControl>
TestDataGridColumn.xaml:
Code:
<DataGridTemplateColumn x:Class="DataGridTestBed.TestDataGridColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
</DataGridTemplateColumn>
TestDataGridColumn.xaml.cs:
Code:
using System.Windows;
namespace DataGridTestBed
{
public partial class TestDataGridColumn
{
private FieldConfig _fieldConfig;
private FieldConfig FieldConfigProperty
{
set
{
_fieldConfig = value;
Header = _fieldConfig.Header;
Visibility = _fieldConfig.Visibility;
}
}
public FieldConfig FieldConfig
{
get
{
return (FieldConfig)GetValue(FieldConfigPropertyProperty);
}
set
{
SetValue(FieldConfigPropertyProperty, value);
}
}
public static readonly DependencyProperty FieldConfigPropertyProperty =
DependencyProperty.Register("FieldConfig", typeof(FieldConfig), typeof(TestDataGridColumn), new UIPropertyMetadata(FieldConfigChangedHandler));
public static void FieldConfigChangedHandler(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
((TestDataGridColumn)sender).FieldConfigProperty = e.NewValue as FieldConfig;
}
public TestDataGridColumn()
{
InitializeComponent();
}
}
}
TestDataGrid.xaml:
Code:
<DataGrid x:Class="DataGridTestBed.TestDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DataGridTestBed"
mc:Ignorable="d"
>
<DataGrid.Resources>
<local:BindingProxy x:Key="Proxy" Data="{Binding}"/>
</DataGrid.Resources>
</DataGrid>
But the main window xaml is way more complicated than I want it to be. Where it says this -
Code:
<local:TestDataGridColumn
FieldConfig="{Binding Data.FirstNameConfig, Source={StaticResource Proxy}}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}"></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</local:TestDataGridColumn >
...I just want it to look like this..
Code:
<local:TestDataGridColumn
FieldConfig="{Binding FirstNameConfig}"
Binding="{Binding FirstName}"/>
... and do the same thing.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|