Get parent datacontext brush from inside a listview - c#

I got the following:
<ListView ItemsSource="{Binding Path=Items}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Path=GridTextColor}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The datacontext looks like this:
class{
items = List with items (each row has a name property)
GridTextColor = Brush
}
I bind the listview with all items. Each item contains a name and that name shows up nicely in the listview.
The problem is that i want all items inside the DataTemplate to have the Foreground set to the brush.
With the code above that is not possible since when i am inside the DataTemplate i bind to the items that are sent in.
Question, how can i bind to the "parent datacontext" to get the correct foreground color?

You can use RelativeSource in your binding to get parent's DataContext.
<TextBlock Text="{Binding Path=Name}"
Foreground="{Binding Path=DataContext.GridTextColor,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=ListView}}"/>
Or Set x:Name on ListView and bind using ElementName:
<ListView x:Name="myListView">
....
<TextBlock Text="{Binding Path=Name}"
Foreground="{Binding DataContext.GridTextColor,
ElementName=myListView}" />
....
</ListView>

Related

C# WPF Listbox Group Header Style

I'm using a Listbox to show multiple items.
The items are grouped. Now I want to edit the header style but the only thing happens is that the text isn't shown anymore.
Thats my xaml:
<ListBox x:Name="lbTreatments" HorizontalAlignment="Left" Height="473" Margin="10,37,0,0" VerticalAlignment="Top" Width="309" FontSize="13">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding subcategoryName}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And thats my code to group the items:
ICollectionView view = CollectionViewSource.GetDefaultView(treatmentsCategory);
view.GroupDescriptions.Add(new PropertyGroupDescription("subcategoryName"));
view.SortDescriptions.Add(new SortDescription("subcategoryName", ListSortDirection.Ascending));
lbTreatments.ItemsSource = view;
The items are grouped but the header text is missing. If I delete the Groupstyle from xaml the text will be shown. Can anybode help me please?
MSDN says:
Each group is of type CollectionViewGroup.
The actual data type is CollectionViewGroup which doesn't have a subcategoryName property so the binding will fail. Instead you have to use the Name property, which will already be set to the value from subcategoryName.
As such, use this...
<TextBlock Text="{Binding Name}"/>
...in your header template to get the group name.

Combobox not showing groupings

I'm trying to organize the items in a combobox into groups. To do this I've created an object that has project and group name strings. I then set the GroupStyle and ItemTemplate to display these values. However, Currently, only the project string is displayed in the combobox (and the box has a red border, indicating some kind of error).
Here's the xaml for my combobox:
<ComboBox x:Name="comboBoxProjects" Margin="165,90,28,0" Grid.Column="0" VerticalAlignment="Top" Height="25"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Style="{StaticResource ComboBoxDefault}"
ItemsSource="{Binding Path=ProjectClientSelections.ProjectGroupItems,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=ProjectClientSelections.SelectedProject, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding GroupName}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Project}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Does anyone see where I'm going wrong?
In GroupStyle, the DataContext is not your item (the type contained in your ItemsSource), but a CollectionViewGroup object, which is formed based on the collection of items that you have grouped. Because of this you have to declare a binding path to one of the properties in CollectionViewGroup, for example, based on your code you probably want to use Name property. See MSDN CollectionViewGroup Class
Change your GroupStyle.HeaderTemplate to this:
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
You don't show how you have formed your GroupDescriptions. If you have not grouped the items already, you can do it in following way (assuming the XAML you have provided is contained inside Window and Window's and GroupBox's DataContext is the same):
<Window.Resources>
<CollectionViewSource
Source="{Binding ProjectClientSelections.ProjectGroupItems}"
x:Key="GroupedProjectItems">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription
PropertyName="GroupName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
After this change GroupBox ItemSource binding to the following (directly to CollectionViewSource resource):
ItemsSource="{Binding Source={StaticResource GroupedProjectItems}}"

How to make same color for treeview item and parent?

I am creating Treeview in wpf.
Each parent item set random foreground color using converter.
I want all its children to set the same color. using only xaml.
Here is part of my code:
<HierarchicalDataTemplate DataType="{x:Type sotc:Category}"
ItemsSource="{Binding Path=NoteList}">
<TextBlock Text="{Binding Path=Name}" Forground="{Binding Path=Name, Convert={StaticResource Converter1}}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type sotc:Note}">
<TextBlock Text="{Binding Path=Name}" />
</HierarchicalDataTemplate>
What I wish to do is to set the second treeview item (in the xaml code), Children in HierarchicalData the same forgound color as its parent.
Is there a way to do that?
Thank Ahead,
You can try by using the FindAncestor RelativeSource mode.
Just replace your Note template with this one:
<DataTemplate DataType="{x:Type sotc:Note}">
<TextBlock Text="{Binding Path=Name}"
Foreground="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=2, AncestorType=TreeViewItem}, Path=Header.Name, Converter={StaticResource Converter1}}"/>
</DataTemplate>
I used a DataTemplate, but you can keep using a HierarchicalDataTemplate if you prefer.

Value from Binding ElementName producing empty string

I have a Datagrid which has a DataGridTemplateColumn containing a ListView whose Itemsource is bound to an array of string.
Within that ListView I have defined an ItemTemplate as I want the Foreground of each item in the list to be dependant on condition - so that's applied to a TextBlock.
I want a tooltip to display when each item in the ListView is hovered over, so I have a Tooltip defined in that TextBlock
What I'm trying to do is have that Tooltip display the title/detail about a specific item by using a converter (to get the index of the item in a different list).
For this I need the Tooltip to know the ListView item but I can't seem to get that to work. The TextBlock itself retrieves it using Path=., I have tried naming the TextBlock ListItem and retrieving it as ElementName to no avail - the result is just empty string.
Here's the relevant xaml (with formatting properties removed).
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="ListItem" Text="{Binding Path=.}" Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Text, Converter={StaticResource ConvertItemToColour}}">
<TextBlock.ToolTip>
<ToolTip>
<StackPanel Orientation="Vertical">
<Label>
<TextBlock Text="{Binding ElementName=ListItem, Path=Text, Converter={StaticResource ConvertItemToTitle}}"/> <!-- Item Title -->
</Label>
<Label>
<TextBlock/> <!-- Item Description -->
</Label>
</StackPanel>
</ToolTip>
</TextBlock.ToolTip>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
ToolTip, like Popup, is not part of the main visual tree so neither ElementName nor RelativeSource binding will work beyond ToolTip but DataContext inside ToolTip should still be the same as for ListViewItem
<ToolTip>
<StackPanel Orientation="Vertical">
<Label>
<TextBlock Text="{Binding Path=., Converter={StaticResource ConvertItemToTitle}}"/>
</Label>
</StackPanel>
</ToolTip>
Text="{Binding Path=.}" should give you same result inside ToolTip as in DataTemplate

WPF: How to select parent listbox if user clicked on child listbox

In my application using DataTemplate mechanism I insert into ListBox item another listbox. But is it possible that when selected one listboxitem in parent listbox, the focus may be on another parent listboxitem's child (see picture)
How to do: if one of child listbox in focus (one item from them selected), then parent listboxitem being selected to? Using binding or templating
<DataTemplate x:Key="NotesListBoxDataTemplate" DataType="Note">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<my:DatePicker Height="25" Name="datePicker1" Width="115" xmlns:my="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit"
SelectedDate="{Binding LastEdit,
Mode = TwoWay}" />
</StackPanel>
<TextBox Text="{Binding Path=Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<StackPanel Orientation="Horizontal">
<ListBox Name="ImagesListBox" SelectedIndex="{Binding Mode=OneWayToSource, Source={StaticResource progParameters}, Path=SelectedImage, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding Path=Images}" ItemTemplate="{StaticResource NotesListBoxImagesTemplate}" Style="{StaticResource HorizontalListBox}">
</ListBox>
<StackPanel Orientation="Vertical">
<Button Name="AddImageButon" Content="+" Click="AddImageButon_Click"></Button>
<Button Name="RemoveImageButon" Content="-" Click="RemoveImageButon_Click"></Button>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
On the parent ListBox set property IsSynchronizedWithCurrentItem to true, then in the inner ListBoxes set the SelectedItem property to "{Binding SelectedItem ElementName=lbParent}".
Consider using a Converter to help you get specific data that is not accessible thru xaml or if you need to do some caculations.
Hope this helps.

Categories

Resources