How to get current cell value in GridView binding - wpf

Having spent the last few hours with this rather simple problem, I haven't yet found a way to do it. I'm using a GridView to display some data and need to perform some customization of the cell values using a converter. Here is the relevant XAML:
<ListView ItemsSource="{Binding SomeDataTable}">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=XXX, Converter={StaticResource MyConverter}}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
What do I need to write in place of XXX above?
N.B. I cannot put constant column name here because this DataTemplate is to be used by all columns of GridView. I need a way to refer to current cell value just like how GridView's default template works when using DisplayMemberBinding.
I found a relevant post here, but that also doesn't have any working answer.

One option is to use DisplayMemberBinding to create the GridViewColumns and then to define your TextBlock's style as a resource of your ListView and to use a converter there.
Given a scenario where I have a list of persons and I want to color all the cells based on the person's age:
Data item:
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
public Person(int age, string name)
{
Age = age;
Name = name;
}
}
Creating the columns in XAML:
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Age}" />
<GridViewColumn DisplayMemberBinding="{Binding Name}" />
</GridView>
</ListView.View>
The converter which changes cell background based on the age:
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((int) value < 20)
{
return Brushes.LightBlue;
}
return Brushes.LightGreen;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
Using the converter:
<ListView.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Background">
<Setter.Value>
<Binding Path="Age">
<Binding.Converter>
<local:MyConverter/>
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
Result:
Full XAML:
<ListView x:Name="MyItems" Loaded="MyItems_OnLoaded">
<ListView.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Background">
<Setter.Value>
<Binding Path="Age">
<Binding.Converter>
<local:MyConverter/>
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Age}" />
<GridViewColumn DisplayMemberBinding="{Binding Name}" />
</GridView>
</ListView.View>
</ListView>

Related

How to select checkbox in ListView from code - WPF

I have a ListView with checkboxes like this:
<ListView
x:Name="usersListView"
Width="300"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
SelectionChanged="childrenListView_SelectionChanged"
Background="{StaticResource BackgroundPrimaryBrush}"
Foreground="{StaticResource WhiteBrush}"
Grid.Row="6" Grid.ColumnSpan="2"
>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding Id}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding FullName}" Header="Name" Width="250"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
All checkboxes in ListView are from List 'AllUsers' from database.
Now I want to set specific checkboxes to IsChecked=True in code behind.
I have another List 'Children' which have only few of the 'AllUsers' elements.
What I want is to display ListView with selected checkboxed binded to Persons in 'Children'.
I tried to implement this by myself with INotifyPropertyChanged implemented class wrapper to Person but I couldn't get Binding properly with this.
I hope I did explain the problem properly.
Thank you in advance :)
Consider using a IMultiValueConverter.
In the example below, my Children object is a simple string with the name. I have two list, the AllChildrens list and the SelectedChildrens list.
Foreach element in the AllChildrens collection, the converter checks if the element is contained into SelectedChildrens collection.
XAML: (I've removed the events)
<ListView ItemsSource="{Binding AllChildrens}" Tag="{Binding SelectedChildrens}">
<ListView.Resources>
<local:IEnumerableContainsConverter x:Key="Contains" />
</ListView.Resources>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Content="{Binding}">
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource Contains}">
<Binding Path="." />
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListView}}" Path="Tag" />
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding FullName}" Header="Name" Width="250"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
ViewModel:
public class Model
{
public Model()
{
AllChildrens = new List<string>()
{
"James",
"Annabelle",
"Kevin",
"William",
"Joseph",
};
SelectedChildrens = new List<string>()
{
"James",
"Annabelle",
"William",
};
}
public List<string> AllChildrens { get; set; }
public List<string> SelectedChildrens { get; set; }
}
Converter:
class IEnumerableContainsConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values != null &&
values.Length == 2 &&
values[0] is string current_children && // Replace with your children object type
values[1] is IEnumerable<string> selected) // Replace with your children object type
{
return selected.Contains(current_children);
}
return false;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

How to change WPF listview row background colour dynamically?

I am new to WPF, I have the following xaml code for list view:
<ListView x:Name="listView1" ItemsSource="{Binding Processes1}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="470" Margin="10,95,150,6" Width="565" SelectionChanged="NetscalerCfgView_listView1_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="Line" DisplayMemberBinding="{Binding srcCfgLineNum}"/>
<GridViewColumn Header="Source Config" DisplayMemberBinding="{Binding srcConfigText}"/>
</GridView>
</ListView.View>
</ListView>
I have the class SrcListViewInfo which I am displaying in listview:
public class SrcListViewInfo
{
public int srcCfgLineNum { get; set; }
public string srcConfigText { get; set; }
}
I have declared it in windows load event like this:
public ObservableCollection<SrcListViewInfo> processes1 = null;
processes1 = new ObservableCollection<SrcListViewInfo>();
I want to color the row background dynamically in a different function under different cases dynamically, for example:
case DiffResultSpanStatus.DeleteSource:
for (i = 0; i < drs.Length; i++)
{
SrcListViewInfo newInfo = new SrcListViewInfo();
newInfo.BackgroundColor = new SolidColorBrush(Colors.Red);
// newInfo.BackgroundColor = Brushes.Red;
newInfo.srcCfgLineNum = cnt;
newInfo.srcConfigText = ((TextLine)source.GetByIndex(drs.SourceIndex + i)).Line;
// newInfo.BackgroundColor = Brushes.Red; << want to set the color like this.
I have tried solid brush but it does not seem to be working correctly.
You can Style the ListViewItem in xaml directly,
Example:
Assuming your "Name" variable is a string, you can try
<ListView Name="whatever">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Name}"
Value="John">
<Setter Property="Background"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Resources>
....
Now any ListView Row with "Name" Value of "John" will have a "Red" Background
an option
is to use IMultiValueConverter in ListView.ItemTemplate
<ListView DataContext="{Binding}" ItemsSource="{Binding Models}" AlternationCount="3" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name }"/>
<TextBlock Text="{Binding Desc }"/>
<StackPanel.Background>
<MultiBinding Converter="{StaticResource BackConverter}">
<Binding />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}"/>
</MultiBinding>
</StackPanel.Background>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
public class BackConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// write your logic (You have the model and the view model)
var index = ((ItemsControl)values[1]).Items.IndexOf(values[0]);
if (index % 2 == 0)
return Brushes.Gray;
return Brushes.White;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
another option
is to use ItemsControl.AlternationIndex in ListView.ItemContainerStyle
<ListView DataContext="{Binding}" ItemsSource="{Binding Models}" AlternationCount="3" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter Property="Background" Value="Red" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Green" />
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="2">
<Setter Property="Background" Value="Blue" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Edit
public MainWindow()
{
InitializeComponent();
lv.ItemsSource = new List<string> { "a", "b", "c", "d", "e" };
}
After some googling i found out my own solution I am using Listview.ItemsSource and as source i use List with ListViewItems Then i can set background of specify ListViewItem in List, and just refresh listview.
XAML:
<ListView x:Name="listView" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.Row="1">
<ListView.View>
<GridView>
<GridViewColumn Header="IP" DisplayMemberBinding="{Binding IP}" Width="Auto"/>
<GridViewColumn Header="PING" DisplayMemberBinding="{Binding Ping}" Width="Auto"/>
<GridViewColumn Header="Host Name" DisplayMemberBinding="{Binding DNS}" Width="Auto"/>
<GridViewColumn Header="Mac" DisplayMemberBinding="{Binding MAC}" Width="Auto"/>
<GridViewColumn Header="Výrobce" DisplayMemberBinding="{Binding Manufacturer}" Width="Auto"/>
</GridView>
</ListView.View>
</ListView>
Fill ListView with Items with Gray Background:
List<ListViewItem> ITEMS = new List<ListViewItem>();
private void button_Click(object sender, RoutedEventArgs e)
{
for (int i = 1; i < 20; i++)
{
ListViewItem OneItem = new ListViewItem();
OneItem.Background = Brushes.LightGray;
OneItem.Content = new Device() { IP = "1.1.1.1", Ping = "30ms", DNS = "XYZ", MAC = "2F:3C:5F:41:F9", Manufacturer = "Intel" };
ITEMS.Add(OneItem);
listView.ItemsSource = ITEMS;
}
listView.Items.Refresh();
}
public class Device
{
public string IP { get; set; }
public string Ping { get; set; }
public string DNS { get; set; }
public string MAC { get; set; }
public string Manufacturer { get; set; }
}
Create Method for Row Change Color:
private void ChangeRowColor(int RowIndex,SolidColorBrush NewBackground)
{
ITEMS[RowIndex].Background = NewBackground;
listView.Items.Refresh();
}
And use it:
private void button1_Click(object sender, RoutedEventArgs e)
{
ChangeRowColor(4, Brushes.Green);
}

WPF XAML listview - turn a visually shown '1' in a cell into a visually show word in the same cell at displaytime

I've got a listview displaying this (more or less):
--------------------------------------------------------
| Rule no. | Rule Type | Rule Name | Priority | Active |
--------------------------------------------------------
| 1 | 1 | My Rule | 1 | 1 |
--------------------------------------------------------
using this XAML:
<ListView.View>
<GridView>
<GridViewColumn Header="Rule No" DisplayMemberBinding="{Binding Path=RuleNo}" Width="150" />
<GridViewColumn Header="Rule Type" DisplayMemberBinding="{Binding Path=RuleTypeNo}" Width="75">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=RuleTypeNo}" Value="1">
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Rule Name" DisplayMemberBinding="{Binding Path=RuleName}" Width="430"/>
<GridViewColumn Header="Priority" DisplayMemberBinding="{Binding Path=RulePriority}" Width="50"/>
<GridViewColumn Header="Active" Width="50">
<GridViewColumn.CellTemplate>
<HierarchicalDataTemplate>
<CheckBox Visibility="Visible" Name="chkActive" IsChecked="{Binding RuleActive}">
<TextBlock Text=" "/>
</CheckBox>
</HierarchicalDataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
All I want to do is for the RuleTypeNo column change the data value
1
into the word
App
and the value
2
into the word
Dial
visually at runtime in the listview cell. E. g. if the column contains a 1, show a word, if the column contains a 2, show another word.
This appears almost impossible, I've spent about 9 hours straight on this now. As you can see I attempted to use a datatrigger to do this, but it apparently never fires. I've tried various setters, but I either cannot get the setter to be be valid markup, or nothing happens when the listview displays - e. g. the trigger is apparently ignored.
What am I doing wrong? I've searched extensively, but nobody appears to want to interpret actual data in a cell via-trigger to show it in another form - turn a number into a word - everybody wants to change colors, font etc. - I do not want to change the style, I want to change the displayed value in the cell for the Rule Type Number...
How can I change a visually displayed value in a cell into another displayed value in the same cell in an XAML listview? I just want to interpret a '1' into "App" and a '2' into "Dial", visually.
You could try creating a ValueConverter to change the value.
Include the converter in the Resources section of your XAML with:
<src:MyConverter x:Key="myConverter"/>
And then adjust your binding:
<GridViewColumn DisplayMemberBinding="{Binding Path=RuleNo,
Converter={StaticResource myConverter}}}"/>
The converter would look something like:
[ValueConversion(typeof(int), typeof(String))]
public class MyConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
int number = (int)value;
if (number == 1)
return "App";
if (number == 2)
return "Dial";
...
}
public object ConvertBack(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
....
}
}
That said, my personal preference would be to expose a new property called e.g. RuleTypeDescription on the thing you're binding too; instead of binding to the number.
EDIT
If you want to do it with triggers, you can do something like:
<GridViewColumn Header="Thingy">
<GridViewColumn.CellTemplate>
<DataTemplate DataType="{x:Type WpfTests:Item}">
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding MyNumber}" Value="1">
<Setter Property="Text" Value="One"/>
</DataTrigger>
<DataTrigger Binding="{Binding MyNumber}" Value="2">
<Setter Property="Text" Value="Two"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Note that we aren't setting DisplayMemberBinding or binding to the Text attribute in the TextBlock element.

Localize currency values in WPF GridView with different cultures for each row based on XAML bindings to culture name property

First time poster here but have been reading SO for ages and finally have run into a question that I've not been able to answer.
I've got a ListView hosting a GridView with multiple columns. One displays a price and another displays a currency code (CAD, USD, GBP, etc). This is all pulled out of SQL server using Entity Framework so the GridView is databound to a IEnumerable which stores the result of my query. The currency code is stored in a separate table with a localization string (en-US, en-GB) which (in a WinForms version of this app) was previously used in String.Format() to localize the currency to display the appropriate currency format and symbol.
The problem I have is in XAML binding the ConverterCulture of the Price binding to the Currency.LocalizedCultureName to get it to format correctly. Here's my current XAML:
<ListView Grid.Column="0" Name="pricingListingListView" ItemsSource="{Binding Source={StaticResource pricesByYear}}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Header="{Binding Name}" Margin="0,0,0,10">
<ItemsPresenter/>
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Date" DisplayMemberBinding="{Binding Source.Date}" Width="60" />
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Price" DisplayMemberBinding="{Binding Price, StringFormat='{}{0:C}', ConverterCulture={Binding Currency.LocalizedCultureName}}" Width="60" />
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Currency" DisplayMemberBinding="{Binding Currency.Code}" Width="60" />
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Unit" DisplayMemberBinding="{Binding Unit.Name}" Width="60" />
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Source" DisplayMemberBinding="{Binding Source.Name}" Width="125" />
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Project" DisplayMemberBinding="{Binding Project.Description}" Width="125" />
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Plant Type" DisplayMemberBinding="{Binding Project.Plant.Name}" Width="100" />
</GridView>
</ListView.View>
</ListView>
PricesByYear is simply a CollectionViewSource which pulls the IEnumerable out of a DP in my code behind. The data is pulled out correctly, just not formatted.
This compiles fine, but generates a XamlParseException when I load the window containing it: A 'Binding' cannot be set on the 'ConverterCulture' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
The line generating the error is: <GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Price" DisplayMemberBinding="{Binding Price, StringFormat='{}{0:C}', ConverterCulture={Binding Currency.LocalizedCultureName}}" Width="60" />
The short-form objective is to display the price, but format it according to the culture name stored as a string value. Each row in the gridview could potentially be different. As it seems I cannot bind within a binding, is there an alternative way I could go about this?
Answer
Multibinding did the trick, here's the working XAML:
<local:LocalizeCurrencyMultiConverter x:Key="localizeCurrencyMultiConverter"/>
...
<GridViewColumn HeaderContainerStyle="{StaticResource leftAlignedColumnHeader}" Header="Price" Width="60">
<!--DisplayMemberBinding="{Binding Price, StringFormat='{}{0:C}', ConverterCulture={Binding Currency.LocalizedCultureName}}"-->
<GridViewColumn.DisplayMemberBinding>
<MultiBinding Converter="{StaticResource localizeCurrencyMultiConverter}">
<Binding Path="Price"/>
<Binding Path="Currency.LocalizedCultureName"/>
</MultiBinding>
</GridViewColumn.DisplayMemberBinding>
</GridViewColumn>
And the converter class:
public class LocalizeCurrencyMultiConverter :System.Windows.Data.IMultiValueConverter {
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
string localizedCurrency;
if (!values.Any() || values[0] == null)
throw new ArgumentException("Convert requires a minimum a price to display, and optionally a culture.");
double originalCurrency;
if (!double.TryParse(values[0].ToString(), out originalCurrency))
return values[0];
string localization = (values[1] ?? "en-CA").ToString();
try {
localizedCurrency = string.Format(System.Globalization.CultureInfo.CreateSpecificCulture(localization), "{0:c}", originalCurrency);
} catch {
localizedCurrency = string.Format(System.Globalization.CultureInfo.CreateSpecificCulture("en-CA"), "{0:c}", originalCurrency);
}
return localizedCurrency;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
return null;
}
}
Works like a charm.
Use a MultiBinding with a binding to the Price property and a binding the Culture property,
Write a MultiValueConverter and use the values to output the string you want.
I am going to make it easy for you:
MSDN MultiBinding
MSDN MultiConverter

How to add tooltip text on my Gridview column header, WPF VS2010

Here is my grid i what to give an explanation to the header "RED.BROJ" when on mouse over that header to show the expl. text.
<ListView.View>
<GridView>
<GridViewColumn Width="50"
Header="Реd.Број"
DisplayMemberBinding="{Binding Path=RedenBroj}">
</GridViewColumn>
You could do this:
<GridViewColumn Width="50"
DisplayMemberBinding="{Binding Path=RedenBroj}">
<GridViewColumn.Header>
<TextBlock Text="Ред.Број"
ToolTip="Your explanation" />
</GridViewColumn.Header>
</GridViewColumn>
Slightly late response but you can add a tooltip, without losing the ability to drag columns to reorder them, by doing the following:
<GridViewColumn Width="50"
Header="Реd.Број"
DisplayMemberBinding="{Binding Path=RedenBroj}">
<GridViewColumn.HeaderContainerStyle>
<Style>
<Setter Property="Control.ToolTip" Value="Tool tip content"/>
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>
Update: more concise version thanks to LPL
Further update: I wanted to be able to have all columns have tooltips that match their headers (as some columns were too narrow to show the whole header):
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="ToolTip"
Value="{Binding Content, RelativeSource={RelativeSource Self}}"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn DisplayMemberBinding="{Binding A}" Header="A"/>
<GridViewColumn DisplayMemberBinding="{Binding B}" Header="B"/>
<GridViewColumn DisplayMemberBinding="{Binding C}" Header="C"/>
</GridView>
</ListView>
Nothing like answering an old question with your own...
I was inspired by #Scroog1's answer but seems a bit redundant having a Tooltip which just mimics the content that is there. You usually want the Tooltip because you've abbreviated the column header text.
I created a small AttachedProperty which I set my Tooltip value on the GridViewColumn. I then bind to this from my Style for my GridViewColumnHeader.
Now I just define the Style once, and add it and the AttachedProperty where I want to use it.
Xaml
<Style x:Key="GridViewColumnHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="ToolTip" Value="{Binding Path=Column.(attachedProperties:GridViewColumnHeaderToolTipAttachedProperty.Tooltip), RelativeSource={RelativeSource Self}}" />
</Style>
<GridView x:Key="GridViewFuelConsumption"
x:Shared="False">
<GridViewColumn Header="Ред.Број"
DisplayMemberBinding="{Binding RedenBroj}"
HeaderContainerStyle="{StaticResource GridViewColumnHeaderStyle}"
attachedProperties:GridViewColumnHeaderToolTipAttachedProperty.Tooltip="Your explanation" />
</GridView>
AttachedProperty
public sealed class GridViewColumnHeaderToolTipAttachedProperty : DependencyObject
{
public static readonly DependencyProperty TooltipSourceProperty = DependencyProperty.RegisterAttached(
"Tooltip",
typeof(string),
typeof(GridViewColumnHeaderToolTipAttachedProperty),
new PropertyMetadata("null"));
public static void SetTooltip(DependencyObject element, string value)
{
element.SetValue(TooltipSourceProperty, value);
}
public static string GetTooltip(DependencyObject element)
{
return (string)element.GetValue(TooltipSourceProperty);
}
}

Resources