I have a GridView and want to serialize column widths across sessions. My idea of how to accomplish this is to attach a behavior to the GridViewColumns in such a way that each time the width of a column is changed the attached event handler is called and stores the new width. This already works well.
The only remaining problem:
How do I know in the event handler which GridViewColumn sent the event? I obviously need to know that in order to be able to st开发者_JAVA技巧ore the width and later set the width on the correct column when restoring. Ideally I would like to use the name specified in XAML as column identifier.
Here is my code. XAML:
<GridView>
<GridViewColumn x:Name="GridColumn0"
HeaderTemplate="{StaticResource GridViewHeaderTemplate}" HeaderContainerStyle="{StaticResource GridViewHeaderStyle}"
Header="{x:Static strings:Strings.MainWindow_AppLog_Header_Severity}"
behaviors:GridViewBehaviors.PersistColumnWidth="True">
C# (please scroll down - question at bottom):
// Register the property used in XAML
public static readonly DependencyProperty PersistColumnWidthProperty =
DependencyProperty.RegisterAttached("PersistColumnWidth", typeof(bool), typeof(GridViewBehaviors),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnPersistColumnWidthChanged)));
// Provide read access to the value
public static bool GetPersistColumnWidth(DependencyObject d)
{
return (bool)d.GetValue(PersistColumnWidthProperty);
}
// Provide write access to the value (set from XAML)
public static void SetPersistColumnWidth(DependencyObject d, bool value)
{
d.SetValue(PersistColumnWidthProperty, value);
}
// This gets called once when the XAML is compiled to BAML
// Set the event handler
private static void OnPersistColumnWidthChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
GridViewColumn column = sender as GridViewColumn;
if (column == null)
return;
// Couple the UI event with a delegate
if ((bool)args.NewValue)
((INotifyPropertyChanged)column).PropertyChanged += new PropertyChangedEventHandler(PersistWidth);
else
((INotifyPropertyChanged)column).PropertyChanged -= new PropertyChangedEventHandler(PersistWidth);
}
// Deal with the events
static void PersistWidth(object sender, PropertyChangedEventArgs e)
{
GridViewColumn column = sender as GridViewColumn;
if (column == null)
return;
// We are only interested in changes of the "ActualWidth" property
if (e.PropertyName != "ActualWidth")
return;
// Ignore NaNs
if (column.ActualWidth == double.NaN)
return;
// Persist the width here
// PROBLEM:
// How to get a unique identifier for column, ideally its name set in XAML?
}
I don't think you will be able to access the x:Name, but you should be able to define your own column type that has a Name property that you can set.
So instead of adding GridViewColumns you add NamedColumn objects in your xaml.
Define a type that derives from GridViewColumn:
public class NamedColumn : GridViewColumn
{
public string ColumnName {get; set;}
}
And use it in your xaml:
<GridView>
<NamedColumn ColumnName="GridColumn0" .... blablalba more stuff here />
...
NoW you should be able to cast the sender to a NamedColumn and access its name property.
can you use column.Header.ToString()? see here for why name from XAML isn't possible: How to get x:Name value runtime
Thanks for your answers, Robert, Thomas and Rune. I like Runes answer, but I found something even easier for my situation here:
I changed the type of the attached property from bool to string and simply store the name of the column there. The relevant changes are below.
XAML:
<GridViewColumn
behaviors:GridViewBehaviors.PersistColumnWidth="MainWindow_AppLog_Column0">
C#:
public static readonly DependencyProperty PersistColumnWidthProperty =
DependencyProperty.RegisterAttached("PersistColumnWidth", typeof(string),
typeof(GridViewBehaviors), new FrameworkPropertyMetadata(string.Empty,
new PropertyChangedCallback(OnPersistColumnWidthChanged)));
static void PersistWidth(object sender, PropertyChangedEventArgs e)
{
// This now yields "MainWindow_AppLog_Column0"
string columnID = GetPersistColumnWidth(column);
I'm not sure it would work, but you can try something like that:
INameScope nameScope = NameScope.GetNameScope(column);
string name = nameScope
.Where(kvp => kvp.Value == column)
.Select(kvp => kvp.Key.ToString())
.FirstOrDefault();
精彩评论