Bind to current item in ItemsControl from UserControl's DataContext [duplicate] - wpf

This question already has answers here:
Issue with DependencyProperty binding
(3 answers)
XAML binding not working on dependency property?
(1 answer)
Binding to custom control inside DataTemplate for ItemsControl
(1 answer)
Closed 1 year ago.
Inside an ItemsControl, I am trying to set a property of a custom UserControl conditionally using a DataTrigger, however, the DataContext in the DataTrigger is that of the UserControl, and not the current item in the list.
In the XAML below Status is a property of an item in ListOfItems. How can I bind to the Status property of the current list item?
Edit: In local:Icon I have set the DataContext, without setting it does work, but I want to know if it is also possible otherwise.
<ItemsControl Margin="5 0 0 0" ItemsSource="{Binding ListOfItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Style="{StaticResource HorizontalStackPanel}">
<local:Icon Width="18" Height="18">
<local:Icon.Style>
<Style TargetType="local:Icon">
<Style.Triggers>
<!-- DataContext is Icon, but I want current item from ListOfItems -->
<DataTrigger Binding="{Binding Status}" Value="Default">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</local:Icon.Style>
</local:Icon>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I know that RelativeSource can be used to access for example a parent DataContext, but I do not know how or if this can be used for my problem.

Related

Address a property of parent ListView from a listview item

Desired: set border properties of a listview depending on conditions in displayed items. For example:
Set the border of an entire ListView red if any one of its (string) items begins with "S". So the problem is how to address a parent listview from its items (within xaml preferably)
Something like
<ListView Name="lv" Grid.Row="2" ItemsSource="{Binding TheItemList}" Height="100" BorderBrush="Black">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding }">
<TextBlock.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Converter={StaticResource StringToBoolean}}
Value="True">
<Setter ???? Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
(where the converter is the obvious thing) does not work: I can' use
TargetName="lv" in the ???? part of the setter, that's outside the scope. Neither can I use <Style TargetType="ListView"> in the style declaration. I could of course go up and back through the view model, but how does one do this in .xaml?
Must be having a bad day, this seems like an obvious thing. My googling hasn't yielded much unfortunately.
A setter in a Style can only set a property of the element to which the Style is applied, i.e. a Style for a TextBlock cannot set the property of the parent ListView.
You could "move" the Style to the ListView and implement the converter to return true if ListBox.Items.OfType<string>().Any(x => x?.StartsWith("s") == true) or something similar.
But a Style for a child element cannot set a property of the parent element.

Binding in Style Setter in DataTemplate WPF

Okay, I have a relatively involved problem. I'm trying to create a Window in WPF. The main element on this window is a DataGrid. Each one of the rows in the DataGrid has a DetailsPane which I set using DataGrid.RowDetailsTemplate. Depending on certain row-specific values, I need the DetailsPane to display different elements. To accomplish this I placed a ContentControl at the root of the DataTemplate and used a Style with DataTriggers to set its Content property. Now, inside one of these Setters is a ComboBox. This ComboBox needs to have its ItemsSource bound to a list, which is stored in a dependency property on the Window level (because its the same list regardless of the row). Below is a simplified version of what I'm looking at:
<Window>
...
<DataGrid>
...
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<ContentControl>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding RowSpecificBooleanProperty}" Value="False">
<Setter Property="Content">
<Setter.Value>
...
<ComboBox ItemsSource={HowDoIBindThisToTheWindowProperty}/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Window>
So what I'm trying to figure out is how to bind the ItemsSource of that ComboBox to a dependency property of the top-level window. Andy idea how to accomplish that?
EDIT:
I should have mentioned this before but I've already tried using {RelativeSource AncestorType=Window} and ElementName in the binding. In both cases the list in the ComboBox is blank at runtime.
ItemsSource="{Binding WhateverList, RelativeSource={RelativeSource AncestorType=Window}}"

WPF IValueConverter for DataGrid.Cell Tooltip Visibility getting null Value in Convert

XAML for Converter
<ToolTip x:Key="toolTipGridCell" DataContext="{Binding Path=PlacementTarget,
RelativeSource={x:Static RelativeSource.Self}}"
Visibility="{Binding Path=PlacementTarget,
RelativeSource={x:Static RelativeSource.Self},
Converter={StaticResource ContentFitsVisibilityConverter}}">
<TextBlock FontWeight="Bold" Text="{Binding Path=Content.Text}"/>
</ToolTip>
....
<DataGrid ....>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="ToolTip" Value="{StaticResource toolTipGridCell}" />
</Style>
</DataGrid.CellStyle>
I need to either hide or show the tooltip on the cell bases on whether the content of that cell is fully visible given the cell's width.
When I remove the Visibility part of the ToolTip, I get the tool tip with cell contents - so the targeting seems to be correct.
But with the visibility defined as above, when the Convert function gets hit as I mouse over the cell, the first parameter (object value) is null, instead of being the DataGrid.Cell over which the tooltip is showing up.
In the Sample Code you have provided, both the datacontext and the visibility of the Tooltip control are bound to the same property "PlacementTarget". This caused the NullReferenceException. To Resolve this issue, bind datacontext and the visibility to the appropriate property in your viewmodel.

Conditionally changing the Foreground of a WPF ComboBox item depending upon a value in the databound ItemsSource item

I have a WPF ComboBox bound to a Collection List<Users>. I have applied a DataTemplate to show the FirstName using a TextBlock and this works as expected:
<ComboBox Margin="5" ItemsSource="{Binding Path=TheUsers}" Name="cboUsers">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="10" Text="{Binding Path=FirstName}">
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>`
I have an item in my User class called IsActive which is a Boolean value. If true then I want to set the Foreground of the TextBlock to Navy.
I have spent so much time on what should be so easy and looked all over the web but most articles talk about changing the overall colour or binding to another element in the xaml.
I tried implementing a DataTrigger and after an hour removed the code because it was not working. It would not recognise my field name. Does anyone have a very simple guide to how to do this or what would be the best approach?
As you apparently are not dealing with fields after all, this style should do what you want:
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Foreground" Value="Navy"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
It would not recognise my field name.
You cannot bind to fields, end of story.

Bind focus to datacontext in WPF

I would like to bind the current focus to the datacontext. My menu system has a viewmodel that contains a list of ButtonViewModels as datacontext. How would I go about having the focused button be determined by the datacontext?
There is a FocusManager.FocusedElement, but this references to a control and the idea of a ViewModel is to not depend on the implementation of the View...
I tried to place a DataTrigger in the Button Style which binds to a property called IsFocused in the ButtonViewModel and in the Setter Bind FocusManager.FocusedElement to the Button where IsFocused is set to true. This should allow you to Control the Focus directly from the ButtonViewModel
<ItemsControl ItemsSource="{Binding ButtonViewModels}">
<ItemsControl.Resources>
<Style x:Key="FocusBindingStyle" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused}" Value="True">
<Setter Property="FocusManager.FocusedElement"
Value="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="Test" Style="{StaticResource FocusBindingStyle}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Resources