I have a button in WPF and I want to make it visible if the mouse is over the border the button is in. This is simple:
<Button Grid.Column="1" Click="DimFilter_Click" Style="{StaticResource ImageButton}" MouseDown="Button_MouseDown"
Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Border}}, Path=IsMouseOver, Converter={StaticResource BoolToVis}}">
<Button.Content>
<Image Source="{Binding FilterActive, Converter={StaticResource FilterImageConverter}}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Button.Content>
</Button>
My problem is that I also want to make button visible if the Property "FilterActive" is true.
So if "FilterActive" is false I want to use the MouseOver Binding in the Code above, but if "FilterActive" is true, the Button should be visible all the time, ignoring the first binding.
Is this possible in any way?
You could use triggers rather than a binding:
<Button Grid.Column="1"
Click="DimFilter_Click"
MouseDown="Button_MouseDown">
<Button.Style>
<Style BasedOn="{StaticResource ImageButton}" TargetType="Button">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding FilterActive}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Border}}, Path=IsMouseOver, Converter={StaticResource BoolToVis}}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
<Image Source="{Binding FilterActive, Converter={StaticResource FilterImageConverter}}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Button.Content>
</Button>
Okay I got it, stupid me.
<Button.Visibility>
<MultiBinding Converter="{StaticResource ButtonVisConverter}">
<Binding Path="FilterActive"/>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Border}}" Path="IsMouseOver"/>
</MultiBinding>
</Button.Visibility>
The code in the converter is pretty much self explanatory
Related
i have a dxg:GridControl in which i have dxg:GridColumn and on every row there is a Display and Edit template like below
<dxg:GridControl>
<dxg:GridControl.Columns>
<dxg:GridColumn Width="101"
AllowBestFit="True"
AllowColumnFiltering="True"
AllowSorting="False"
FieldName="Tolerance"
Header="Tolerance Type"
ReadOnly="{Binding IsReadOnly}">
<dxg:GridColumn.EditTemplate>
<ControlTemplate>
<dxe:ComboBoxEdit
x:Name="PART_Editor"
Width="100"
ItemsSource="{Binding Path=DataContext.ToleranceTypeCollection,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}"
SelectedItem="{Binding RowData.Row.Tolerance}"
DisplayMember="ToleranceType"
FilterCondition="Contains"
ImmediatePopup="True"
IncrementalFiltering="True"
IsTextEditable="False"
ValueMember="ToleranceTypeId"
ShowSizeGrip="True"
TextWrapping="WrapWithOverflow"
Style="{DynamicResource DXEComboBoxEditStyle}" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.ToleranceTypeCollection.Count, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="0">
<Setter TargetName="PART_Editor" Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding DataContext.IsReadOnly, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="True">
<Setter TargetName="PART_Editor" Property="IsEnabled" Value="False" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</dxg:GridColumn.EditTemplate>
<dxg:GridColumn.DisplayTemplate>
<ControlTemplate>
<TextBlock Margin="5,0,0,0" VerticalAlignment="Center" Text="{Binding RowData.Row.Tolerance.ToleranceType}" />
</ControlTemplate>
</dxg:GridColumn.DisplayTemplate>
</dxg:GridColumn>
</dxg:GridControl.Columns>
</dxg:GridControl>
the values are coming well on the Display template but while clicking on Cell, the control is changing to dxe:ComboBoxEdit but it is not automatically picking the saved value from List of values in drop down hence the value on Display templates's textbox is being lost after clicking somewhere else.
Using Dev Express v 18.1
Please help on the same
Thank you
I am using MahApps.Metro in my WPF app and trying to change the Maximize/RestoreDown icons of MetrowWindow to the following new FullScreen/BackToWindow icons:
Question: How can we replace the default Maximize/RestoreDown icons of MetrowWindow?
Remarks: As suggested here, I tried the following code but it's still showing the old style - as shown below. I'm probably missing something here and not doing it right. New icons are not an issue. I just need to know how we can replace the old ones with the new ones.
<mah:MetroWindow x:Class="WPF_Mah_Metro_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Mah_Metro_Test"
mc:Ignorable="d"
GlowBrush="{DynamicResource MahApps.Brushes.Accent}"
ResizeMode="CanResizeWithGrip"
WindowStartupLocation="CenterScreen"
Height="450" Width="800">
<mah:MetroWindow.WindowButtonCommands>
<mah:WindowButtonCommands Template="{DynamicResource MahApps.Templates.WindowButtonCommands.Win10}" />
</mah:MetroWindow.WindowButtonCommands>
<Grid>
</Grid>
In order to customize the window buttons, you have to create a custom control template for the type WindowButtonCommands. You can copy one of the default control templates below from GitHub.
MahApps.Templates.WindowButtonCommands
MahApps.Templates.WindowButtonCommands.Win10
I took the Win10 control template and and adapted two things in the PART_Max button:
Change the Data of PART_MaxPath Path to an appropriate path that represents the icon or replace it with a TexBlock that uses the Segoe MDL2 Assets font and displays the gylph.
Change the DataTrigger for Maximized to set the appropriate icon the same way.
In the example below, I used the TextBlock approach, because I do not have path data for the icons. Please be aware, that the Path variant would always work, while the TextBlock variant requires the font to be available on your system.
<ControlTemplate x:Key="MahApps.Templates.WindowButtonCommands.Custom"
TargetType="{x:Type mah:WindowButtonCommands}">
<StackPanel Orientation="Horizontal">
<Button x:Name="PART_Min"
Width="46"
AutomationProperties.AutomationId="Minimize"
AutomationProperties.Name="Minimize"
Command="{x:Static SystemCommands.MinimizeWindowCommand}"
Focusable="False"
IsEnabled="{Binding IsMinButtonEnabled, RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}}"
ToolTip="{Binding Minimize, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
UseLayoutRounding="True">
<Button.Visibility>
<MultiBinding Converter="{x:Static converters:ResizeModeMinMaxButtonVisibilityConverter.Instance}"
ConverterParameter="MIN">
<Binding Mode="OneWay"
Path="ShowMinButton"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
<Binding Mode="OneWay"
Path="UseNoneWindowStyle"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
<Binding Mode="OneWay"
Path="ResizeMode"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
</MultiBinding>
</Button.Visibility>
<Path Width="10"
Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M0,0L10,0 10,1 10,1 1,1 0,1z"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
RenderOptions.EdgeMode="Aliased"
SnapsToDevicePixels="True"
Stretch="Uniform" />
</Button>
<Button x:Name="PART_Max"
Width="46"
AutomationProperties.AutomationId="MaximizeRestore"
AutomationProperties.Name="Maximize"
Command="{x:Static SystemCommands.MaximizeWindowCommand}"
Focusable="False"
IsEnabled="{Binding IsMaxRestoreButtonEnabled, RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}}"
ToolTip="{Binding Maximize, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
UseLayoutRounding="True">
<Button.Visibility>
<MultiBinding Converter="{x:Static converters:ResizeModeMinMaxButtonVisibilityConverter.Instance}"
ConverterParameter="MAX">
<Binding Mode="OneWay"
Path="ShowMaxRestoreButton"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
<Binding Mode="OneWay"
Path="UseNoneWindowStyle"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
<Binding Mode="OneWay"
Path="ResizeMode"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
</MultiBinding>
</Button.Visibility>
<!-- normal state -->
<TextBlock x:Name="PART_MaxPath"
FontFamily="Segoe MDL2 Assets"
FontSize="16"
Text="" />
</Button>
<Button x:Name="PART_Close"
Width="46"
AutomationProperties.AutomationId="Close"
AutomationProperties.Name="Close"
Command="{x:Static SystemCommands.CloseWindowCommand}"
Focusable="False"
IsEnabled="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}, Path=IsCloseButtonEnabled, Mode=OneWay}"
ToolTip="{Binding Close, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
UseLayoutRounding="True">
<Button.Visibility>
<MultiBinding Converter="{x:Static converters:ResizeModeMinMaxButtonVisibilityConverter.Instance}"
ConverterParameter="CLOSE">
<Binding Mode="OneWay"
Path="ShowCloseButton"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
<Binding Mode="OneWay"
Path="UseNoneWindowStyle"
RelativeSource="{RelativeSource AncestorType={x:Type mah:MetroWindow}}" />
</MultiBinding>
</Button.Visibility>
<Path Width="10"
Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="F1M8.583,8L13,12.424 12.424,13 8,8.583 3.576,13 3,12.424 7.417,8 3,3.576 3.576,3 8,7.417 12.424,3 13,3.576z"
Fill="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
RenderOptions.EdgeMode="Aliased"
SnapsToDevicePixels="True"
Stretch="Uniform" />
</Button>
</StackPanel>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}, Path=IsCloseButtonEnabled}"
Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}, Path=IsAnyDialogOpen}"
Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}, Path=IsCloseButtonEnabledWithDialog}"
Value="False" />
</MultiDataTrigger.Conditions>
<Setter TargetName="PART_Close"
Property="IsEnabled"
Value="False" />
</MultiDataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:MetroWindow}}, Path=WindowState}"
Value="Maximized">
<Setter TargetName="PART_Max"
Property="AutomationProperties.Name"
Value="Restore" />
<Setter TargetName="PART_Max"
Property="Command"
Value="{x:Static SystemCommands.RestoreWindowCommand}" />
<Setter TargetName="PART_Max"
Property="ToolTip"
Value="{Binding Restore, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
<Setter TargetName="PART_MaxPath"
Property="Text"
Value="" />
</DataTrigger>
<Trigger Property="Theme"
Value="Light">
<Setter TargetName="PART_Close"
Property="Style"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LightCloseButtonStyle}" />
<Setter TargetName="PART_Max"
Property="Style"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LightMaxButtonStyle}" />
<Setter TargetName="PART_Min"
Property="Style"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LightMinButtonStyle}" />
</Trigger>
<Trigger Property="Theme"
Value="Dark">
<Setter TargetName="PART_Close"
Property="Style"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DarkCloseButtonStyle}" />
<Setter TargetName="PART_Max"
Property="Style"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DarkMaxButtonStyle}" />
<Setter TargetName="PART_Min"
Property="Style"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DarkMinButtonStyle}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Set the custom WindowButtonCommands template MahApps.Templates.WindowButtonCommands.Custom to MetroWindow the same way as in your question. Make sure the control template resource is in scope.
<mah:MetroWindow.WindowButtonCommands>
<mah:WindowButtonCommands Template="{StaticResource MahApps.Templates.WindowButtonCommands.Custom}" />
</mah:MetroWindow.WindowButtonCommands>
I have following ControlTemplate which works fine
<ControlTemplate x:Key="TotalCostsStatisticTemplate">
<StackPanel x:Name="ContentHolderPanel" Visibility="Collapsed"
Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock x:Name="ValueTextBlock" VerticalAlignment="Center"
Style="{DynamicResource PhasingValueTextStyle}">
<TextBlock.Text>
<MultiBinding Converter="{ttConverters:CustomDisplayFormatConverter}">
<Binding Path="FormatSettings" />
<Binding Path="AvailableStatistics.CostsFormat"/>
<Binding Path="TotalCosts" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ShowTotalCosts}" Value="True">
<Setter TargetName="ContentHolderPanel" Property="Visibility" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
But if I add another DataTrigger then the MultiBinding on TextBlock.Text doesn't work when control using this template is loaded for first time i.e. the converter CustomDisplayFormatConverter fires only once with all values as UnsetValue and doesn't fire again (it works fine on reloading the window again).
<ControlTemplate x:Key="TotalCostsStatisticTemplate">
<StackPanel x:Name="ContentHolderPanel" Visibility="Collapsed"
Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock x:Name="ValueTextBlock" VerticalAlignment="Center"
Style="{DynamicResource PhasingValueTextStyle}">
<TextBlock.Text>
<MultiBinding Converter="{ttConverters:CustomDisplayFormatConverter1}">
<Binding Path="FormatSettings" />
<Binding Path="AvailableStatistics.CostsFormat"/>
<Binding Path="TotalCosts" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ShowTotalCosts}" Value="True">
<Setter TargetName="ContentHolderPanel" Property="Visibility" Value="Visible"/>
</DataTrigger>
<!--Trigger causing problem (breaking TextBlock.Text multi binding on first load) -->
<DataTrigger Binding="{Binding IsCostsComplete}" Value="False">
<Setter TargetName="ValueTextBlock" Property="Foreground"
Value="{DynamicResource ManagerErrorBrush}"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
If I place this DataTrigger inside TextBlock.Style it works fine!
Any idea what's wrong?
Update:
Here's how its getting used
<ControlTemplate x:Key="PhasingStatisticValuesTemplate">
<StackPanel x:Name="ContentHolderPanel" Orientation="Horizontal" Visibility="{Binding IsValid, Converter={StaticResource boolToVisibilityConverter}}">
<!-- Other control elements based on various templates -->
<Control Margin="20,10" Template="{DynamicResource TotalCostsStatisticTemplate}"/>
</StackPanel>
</ControlTemplate>
This PhasingStatisticValuesTemplate is used in another ControlTemplate, which is then used inside a DataTemplate, so there is a long hierarchy of ControlTemplates -
<ControlTemplate x:Key="PhasingStatisticsTemplate">
<Grid>
<ScrollViewer Style="{DynamicResource CompactHorizontalScrollViewerStyle}" Name="ScrollContainer">
<Grid Name="ScrollViewerGrid" Background="Transparent">
<ContentControl Template="{DynamicResource PhasingStatisticValuesTemplate}" Name="ScrollViewerContent" />
</Grid>
</ScrollViewer>
</Grid>
</ControlTemplate>
Another useful info. might be that existing style on that TextBlock also updated Foreground, not sure how that can cause this behavior -
<Style x:Key="PhasingValueTextStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsComplete}" Value="False">
<Setter Property="Foreground" Value="{DynamicResource ManagerErrorBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
I have a listbox, and I have the following ItemTemplate for it:
<DataTemplate x:Key="ScenarioItemTemplate">
<Border Margin="5,0,5,0"
Background="#FF3C3B3B"
BorderBrush="#FF797878"
BorderThickness="2"
CornerRadius="5">
<DockPanel>
<DockPanel DockPanel.Dock="Top"
Margin="0,2,0,0">
<Button HorizontalAlignment="Left"
DockPanel.Dock="Left"
FontWeight="Heavy"
Foreground="White" />
<Label Content="{Binding Path=Name}"
DockPanel.Dock="Left"
FontWeight="Heavy"
Foreground="white" />
<Label HorizontalAlignment="Right"
Background="#FF3C3B3B"
Content="X"
DockPanel.Dock="Left"
FontWeight="Heavy"
Foreground="White" />
</DockPanel>
<ContentControl Name="designerContent"
Visibility="Collapsed"
MinHeight="100"
Margin="2,0,2,2"
Content="{Binding Path=DesignerInstance}"
Background="#FF999898">
</ContentControl>
</DockPanel>
</Border>
</DataTemplate>
As you can see the ContentControl has Visibility set to collapsed.
I need to define a trigger that causes the Visibility to be set to "Visible"
when the ListItem is selected, but I can't figure it out.
Any ideas?
UPDATE: Of course I could simply duplicate the DataTemplate and add triggers
to the ListBox in question to use either one or the other, but I want to prevent duplicating this code.
You can style your ContentControl such that a trigger fires when its container (the ListBoxItem) becomes selected:
<ContentControl
x:Name="designerContent"
MinHeight="100"
Margin="2,0,2,2"
Content="{Binding Path=DesignerInstance}"
Background="#FF999898">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}},
Path=IsSelected}"
Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
Alternatively, I think you can add the trigger to the template itself and reference the control by name. I don't know this technique well enough to type it from memory and assume it'll work, but it's something like this:
<DataTemplate x:Key="ScenarioItemTemplate">
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}},
Path=IsSelected}"
Value="True">
<Setter
TargetName="designerContent"
Property="Visibility"
Value="Visible"/>
</DataTrigger>
</DataTemplate.Triggers>
...
</DataTemplate>
#Matt, Thank you!!!
Just had to add a trigger for IsSelected == false as well,
and now it works like a charm!
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
I have a ListBox which is populated from a collection of ViewModels, which uses in place editing, which I do by having a couple of styles which I can apply to parts of the DataTemplate which make them visible/collapsed as required. These look something like:
<Style
x:Key="UnselectedVisibleStyle"
TargetType="{x:Type FrameworkElement}">
<Setter
Property="Visibility"
Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource boolToVis}, ConverterParameter=False}" />
</Style>
<Style
x:Key="SelectedVisibleStyle"
TargetType="{x:Type FrameworkElement}">
<Setter
Property="Visibility"
Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource boolToVis}, ConverterParameter=True}" />
</Style>
With my ListBox having it's ItemTemplate given by something like:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock
Text="{Binding Name}"
Style="{StaticResource UnselectedVisibleStyle}" />
<TextBox
x:Name="textBox"
Text="{Binding Name}"
Style="{StaticResource SelectedVisibleStyle}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
This works fine, but what I want ideally is to have the TextBox automatically selected when a user clicks the item, ideally in a nice generic way I can use throughout my project, and without too much messing around in my codebehind.
Thanks,
DM.
The following change to your selected Style seemed to work for me:
<Style x:Key="SelectedVisibleStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Converter={StaticResource boolToVis}, ConverterParameter=True}"/>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>