Inherit foreground value from the parent just as TextBlock in UWP - c#

When I set the SelectedForeground in my ListViewItem style, the TextBlock inside the item DataTemplate changes the colour on selection, as expected. I would like the same colour to be applied to other elements in the DataTemplate, such as Path or Rectangle:
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="Hello" />
<Path Fill={?} />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
I tried to create a custom control and apply the template:
<ControlTemplate x:Key="myControlTemplate" TargetType="local:myControl">
<Grid>
<TextBlock Text="Hello" />
<Path Fill="{Binding Foreground, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</ControlTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<controls:myControl Template="{StaticResource myControlTemplate}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
In that case the path does inherit the value from the ListViewItemPresenter, but only once - it does not update the value when selection changes.
How can I force the Path.Fill property to update it's colour just as TextBlock does?

You can use relativeSource directly in your listView's item template.
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Width="24"
Height="24"
Fill="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"/>
<TextBlock Text="{Binding}"
x:Name="TitleBlock"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>

Inside a ControlTemplate, the "templated parent" is the control itself, so adding a custom control into the mix isn't going to help you any.
What you probably want is this. I can't test it in UWP here, so let me know if you get any errors.
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="Hello" />
<Path
x:Name="MyPath"
Fill="YellowGreen"
Data="M 0,0 L 16,0 L 16,16 L 0,16 Z"
/>
</Grid>
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}"
Value="True">
<Setter
TargetName="MyPath"
Property="Fill"
Value="{Binding SelectedForeground, RelativeSource={RelativeSource AncestorType=ListView}}"
/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListView.ItemTemplate>

Related

WPF combo box header

I need to show only the Icon in the combo box if the combo box is clicked the icon and the text needs to be shown. As I am not familiar with how to achieve this.
Please help me in achieving this.
<ComboBox Name="cmbColors">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This will show the rectangle and text in the combo box and the drop down of the combo box. But my requirement is only to show the color filled rectangle in the combo box.
I am not sure whether I understand what you are trying to do, but my best guess is that you want to hide the text block if some other control has focus. If so, you can do something like this:
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock x:Name="text" Text="{Binding Name}" />
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="False">
<Setter TargetName="text" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
If you are instead trying to say that you want a different template for the header than for the dropdown, then you could do something like described in one of the answers to this question.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock x:Name="text" Text="{Binding Name}" />
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBoxItem}}}" Value="{x:Null}">
<Setter TargetName="text" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Change background color of a WPF ItemTemplate

I have to change Background color of an ItemTemplate of a ListBox, depending the value of a boolean.
Here is my ListBox :
<ListBox Name="itemListBox"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionChanged="itemListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="200">
<TextBlock FontSize="10"
FontWeight="Bold"
VerticalAlignment="Center"
Text="{Binding Path=Value.DocID}" />
<TextBlock FontSize="10"
VerticalAlignment="Center"
TextWrapping="Wrap"
Text="{Binding Path=Value.Serial}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If the user delete an Item, I want to show him in grey backrgound.
Precision : The ListBox is binded to a Dictionnary, that contains a boolean value "IsDeleted".
Sorry for the poor English.
Thank you
You could use an ItemContainerStyle with a DataTrigger:
<ListBox Name="itemListBox" ScrollViewer.VerticalScrollBarVisibility="Visible" SelectionChanged="itemListBox_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Value.IsDeleted}" Value="True">
<Setter Property="Background" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Width="200">
<TextBlock FontSize="10" FontWeight="Bold" VerticalAlignment="Center" Text="{Binding Path=Value.DocID}" />
<TextBlock FontSize="10" VerticalAlignment="Center" TextWrapping="Wrap" Text="{Binding Path=Value.Serial}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Make sure that the class with the IsDeleted property implements the INotifyPropertyChanged interface correctly if you intend to set the property dynamically and want the background to get updated accordingly.

how to select using a wrap panel as the item panel for listview

I want to show a list of items horizontally and be able to select from this list of items - I have tried using a listview and changing the item template per some posts on stack and I have this:
<ListView Height="Auto" HorizontalAlignment="Left" Margin="24,0,0,0" Name="MachinesListView" VerticalAlignment="Top" Width="1455" Background="#FFF0F0F0" ItemsSource="{Binding Machines}" BorderBrush="#FFF0F0F0" Grid.ColumnSpan="2" Grid.Row="2" SelectionChanged="MachinesListView_SelectionChanged">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth),
RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
ItemWidth="{Binding (ListView.View).ItemWidth,
RelativeSource={RelativeSource AncestorType=ListView}}"
MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
ItemHeight="{Binding (ListView.View).ItemHeight,
RelativeSource={RelativeSource AncestorType=ListView}}" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Height" Value="175"/>
<Setter Property="Width" Value="275"/>
<Setter Property="Margin" Value="5,5,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Gray" BorderThickness="2" CornerRadius="10">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Machine.MachineId}" TextAlignment="Center" Width="Auto" Foreground="#FF639A70" FontSize="19"/>
<TextBlock Text="{Binding Machine.Name}" TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" />
<Image Source="/URM;component/Images/slot_machine-512.png" Height="60" Width="60" />
<TextBlock Text="{Binding Machine.Description}" TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" Margin="0, 5, 0, 0"/>
<TextBlock TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" Margin="0, 5, 0, 0">
<Run Text ="Actual: "/>
<Run Text ="{Binding Actual, StringFormat=' {0:c}'}"/>
</TextBlock>
<TextBlock TextAlignment="Center" Width="Auto" Foreground="Gray" FontSize="15" Margin="0, 5, 0, 0">
<Run Text ="OverShort: "/>
<Run Text ="{Binding OverShort, StringFormat=' {0:c}'}"/>
</TextBlock>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
This works well...I get the overall look and feel that I want from this but only selecting the first item causes the selectionchanged event to fire...
I thought about implementing the items as buttons instead but I thought there might be a more proper way of dealing with this.
Set Background to Transparent on outer most border of ControlTemplate.
<Border BorderBrush="Gray" Background="Transparent"
BorderThickness="2" CornerRadius="10">
By default it's {x:Null} which is not responsive to mouse events.
You will see that item gets selected only in case you click over image
or any control present in template but when you click on empty area
within border, selectionChange event doesn't fire since it is
unresponsive to mouse events (specifically MouseClick in your case). Setting background to Transparent will make it responsive to all mouse events.
Refer to this for more details - {x:Null} Vs. Transparent.

Tooltip style. Can't bind to datacontext

i have one problem with tooltip.
I want to add templated tooltip to button with some information inside.
Here the button with tooltip, which datacontext bounded to some viewmodel:
<fluent:Button DataContext="{Binding NewConnections, Source={StaticResource Locator}}" Command="{Binding AddCloudStorageAccount}" Header="Add Account">
<fluent:Button.LargeIcon>
<Image Source="pack://application:,,,/Icons;component/UI/v1/add_account.png" Width="48"/>
</fluent:Button.LargeIcon>
<fluent:Button.ToolTip>
<ToolTip DataContext="{Binding UserInput.AddAccountsButtonInfo, Source={StaticResource Locator}}" Style="{StaticResource ButtonTooltip}"></ToolTip>
</fluent:Button.ToolTip>
</fluent:Button>
Style:
<Style TargetType="ToolTip" x:Key="ButtonTooltip">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="LightYellow" BorderThickness="0.5" BorderBrush="Maroon">
<StackPanel Orientation="Vertical" Margin="3">
<TextBlock x:Name="_txtText" Text="{Binding Title}"></TextBlock>
<TextBlock x:Name="_txtDescription" Margin="0 10 0 0" Text="{Binding Description}"></TextBlock>
<TextBlock x:Name="_txtHotKeyDescription" Margin="0 10 0 0" Text="{Binding HotKeyDescription}"></TextBlock>
</StackPanel>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
I set some breakpoints to see if viewmodel is accessed. And it's ok. But properties like Title not accessed at all and i see only empty rectangle without any text
Do someone have some ideas?
Just resolved it(set datacontext in border). Maybe someone will be interested in:
<Style TargetType="ToolTip" x:Key="ButtonTooltip">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border Background="LightYellow" BorderThickness="0.5" BorderBrush="Maroon" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ToolTip}}}">
<StackPanel Orientation="Vertical" Margin="3">
<TextBlock x:Name="_txtText" Text="{Binding Title}"></TextBlock>
<TextBlock x:Name="_txtDescription" Margin="0 10 0 0" Text="{Binding Description}"></TextBlock>
<TextBlock x:Name="_txtHotKeyDescription" Margin="0 10 0 0" Text="{Binding HotKeyDescription}"></TextBlock>
</StackPanel>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>

WPF combobox itemtemplate overrides togglebutton style

i have problem with styling the combobox's togglebutton.
my combobox xaml code looks like this:
<ComboBox Width="Auto"
HorizontalContentAlignment="Stretch"
FontFamily="HelveticaNeue-Bold"
FontSize="20"
FontWeight="Bold"
Foreground="#FFC0C0C0"
Padding="0,0,0,0"
Style="{DynamicResource navigationComboBox}"
ItemsSource="{Binding Tournaments}"
SelectedValue="{Binding SelectedTournament}">
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
</ComboBox.Resources>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"
Orientation="Vertical"
Width="auto"
Height="{Binding Tournaments, Converter={StaticResource CollectionToHeightConverter}}"/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemTemplate>
<DataTemplate>
<DockPanel x:Name="comboDock">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImagePathConverter}, ConverterParameter=comboboxitem-line.png}" />
</DockPanel.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="41" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DockPanel x:Name="comboArrow"
Grid.Column="0"
Visibility="Collapsed">
<DockPanel.Background>
<ImageBrush ImageSource="{Binding Converter={StaticResource ImagePathConverter}, ConverterParameter=SportsSubMenuActive.png}" />
</DockPanel.Background>
</DockPanel>
<TextBlock x:Name="comboText"
Grid.Column="1"
FontFamily="HelveticaNeue-Bold"
FontSize="20"
FontWeight="Bold"
Foreground="#FFC0C0C0"
Padding="0,0,10,0"
Text="{Binding Path=Name}"
TextAlignment="Left"
TextWrapping="Wrap" />
</Grid>
</DockPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ComboBoxItem}}" Value="True">
<Setter TargetName="comboArrow" Property="Visibility" Value="Visible" />
<Setter TargetName="comboText" Property="Foreground" Value="#F94B01" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
so i'm trying to remove the background set to on togglebutton, but it is not possible. if i remove the background on itemtemplate, then i can style the toggle button background. is there any special order in the process to prevent me from changing the background of the togglebutton content if it is set in itemtemplate?
thanks in advance guys,
Kristo
Setting a property directly takes priority over any Setter(s). Instead of setting the property directly, use a Style for your DockPanel and use a Setter to set the background similar to what you do in your DataTrigger. That should allow you to change the background property elsewhere.

Categories

Resources