Visualize press the button action and hovering over it in MAUI.NET MVVM - button

I use MAUI.NET with MVVM architecture. Because of this I do not want to manage things through an events.
I want to visualize two moments:
when the user hover over the button
when the user click on the button
After these moments I want to button looks normal as nothing happened.
I just found a way to manage second moment (after the button is pressed).
What I managed to do is to set VisualState in a global ResourceDirectory for a buttons, like this:
<Style TargetType="Button" x:Key="HideButtonStyle">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource MediumDarkColor}" />
<Setter Property="Scale" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource HideColor}" />
<Setter Property="Scale" Value="1.07" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
I tried other state like "Focused".
And the buttons seems to be normal button:
<Button Grid.Row="2" Style="{StaticResource HideButtonStyle}" Text="123" Command="{Binding GetSourceFilePathCommand}"/>
The problem is that some buttons backs to the "normal state" immediately and some not.
When the user click on something else it backs to normal, finally.
I have investigated if this is not due to async in Command, but is not.
It seems that the buttons that come back to normal state (proper in my opinion) are the buttons that fires the dialog.
I would like to that after user press the button, it got a colour etc. for a 2-3 seconds and backs automatically to normal state.
It would be fantastic if I could signalize that user hover over the button with let's say scaling it, and signalize when the user press the button with a colouring it for a moment.

There is currently no IsMouseOver detection mouseover event in maui, you can continue to pay attention to this GitHub proposal.
For clicking button to change color you can use Trigger, refer to the following code:
<Button Text="Click Me">
<Button.Triggers>
<Trigger TargetType="Button"
Property="IsFocused" Value="True">
<Setter Property="BackgroundColor" Value="Pink"/>
</Trigger>
</Button.Triggers>
</Button>
You also change the property to Scale to implement click-to-zoom functionality.

I would like to that after user press the button, it got a colour etc. for a 2-3 seconds and backs automatically to normal state.
Why not use animations then? They are pretty easy to use in MAUI, and since you are not happy with your VisualState "Pressed" approach, you can give it a try.
Example:
private async Task AnimateElement(VisualElement element)
{
isAnimating = true;
await element.FadeTo(0, 300);
await element.FadeTo(1, 300);
isAnimating = false;
}

Related

IsSelectionActive cleared when RowDetailsTemplate clicked

I have a datagrid with row details. When I click in the row details the IsSelectionActive on the datagrid is cleared. Now this only happens on some of my datagrids while others using the exact same styles and templates exabit the correct behavior. Here is my xaml for the DataGridRow. when I click on the details view with the error the background of the detail changes to yellow. Also my IsSelected color is cleared however the IsSelected property is always set.
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=IsSelectionActive }" Value="False"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsSelected}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=IsSelectionActive }" Value="True"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="{DynamicResource PrimaryColor}"/>
<Setter Property="Foreground" Value="White"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
Upon further research I have determined this bug occurs when the datagrid is wrapped in a ScrollViewer. In my case I have a dynamic number of different datagrids that must display in a single view which can then be scrolled. As soon as I replace the ScrollViewer with A StackPanel the bug goes away, but I need the ScrollViewer.

Is it possible to replace/modify Implicit style at run time xamarin forms

I have the need to replace at runtime an implicit style that is located in a merged resource dictionary
for example lets suppose I have
<Style TargetType="Label">
<Setter Property="FontSize" Value="14" />
</Style>
Now I want to replace the all style with something else at runtime. Can this be done?
Above is just a sample.. Nothing todo with theming or anything else, I have the need to replace the all implicit style at runtime.
Can I detect based on TargetType ?
thanks
If I understand your problem correctly, I think that data triggers might help you. For example, you can change FontSize with something like this:
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="FontSize" Value="14" />
<Style.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding isSmallDevice}" Value="True">
<Setter Property="FontSize" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
Actually in this occasion I need to change some fontsizes at runtime based on whether is a small device or not
You can use OnIdiom markup extension to detect Phone or Table or desktop.
<Label Text="Welcome to Xamarin.Forms!">
<Label.Style>
<Style TargetType="Label">
<Setter Property="FontSize">
<Setter.Value>
<OnIdiom
x:TypeArguments="x:Double"
Phone="18"
Tablet="50" />
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>

Customize look of selected element

Is there any possibility to customize the look of the active/selected item in the indicator view? Using Data Template Selector or something?
Data template changes every single item.
My goal is to reach this effect:
Try using trigger when color changes of your view at that time increase view's width or you may use view's PropertyChanged event to detect changes in view. I had a similar kind of requirement today and below code worked for me.
<IndicatorView
x:Name="introductionIndicator"
Grid.Row="2"
HorizontalOptions="Center"
IndicatorColor="{StaticResource PrimaryLightGrayColor}"
SelectedIndicatorColor="{StaticResource PrimaryYellowColor}">
<IndicatorView.IndicatorTemplate>
<DataTemplate>
<BoxView
CornerRadius="10"
HeightRequest="6"
WidthRequest="20">
<BoxView.Triggers>
<Trigger TargetType="BoxView" Property="BackgroundColor" Value="{StaticResource PrimaryYellowColor}">
<Setter Property="WidthRequest" Value="30" />
</Trigger>
</BoxView.Triggers>
</BoxView>
</DataTemplate>
</IndicatorView.IndicatorTemplate>
</IndicatorView>
result:

Styles on buttons with children

I have a question about styles. In my Windows Universal application I have certain buttons. These buttons have a stackpanel as a child and the stackpanel has an image as a child. The purpose of this is that the button needs to contain an image.
Now my employer wants to ignore the theme settings of the user. So whenever a button is clicked he doesn't want the background color of the button to change. The only way I've found so far to do this is with a style. However when I use a style the button is displayed without it's children. The style I made looks like this:
<Style x:Key="Button_style" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Pressed">
</VisualState>
<VisualState x:Name="Disabled"/>
<VisualState x:Name="PointerOver">
</VisualState>
<VisualState x:Name="Pointerleave">
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused"/>
<VisualState x:Name="PointerFocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This was a proof of concept. However since the children of the buttons dissapear I'm unable to go on. How would I rewrite this style to make the children of the button stay where they are supposed to be?
Here is some sample code of the button I have:
<Button Name="MyButton" Click="MyButton_Click" ClickMode="Press" HorizontalAlignment="Center" VerticalAlignment="Stretch" >
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left" >
<Image Name="MyImage" x:Uid="MyImage" Source="" VerticalAlignment="Top" HorizontalAlignment="Left" MaxWidth="30" />
</StackPanel>
</Button>
If you want to ignore user settings at all the best option will be just override PhoneAccentBrush value. You can do it in App.xaml, or use ResourceDistionary.
<Color x:Key="PhoneAccentColor">Blue</Color>
Also it is possible to request light or dark theme for your application in App.xaml:
<Application x:Class="App1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App2"
RequestedTheme="Light">
</Application>

Custom DataGrid Row Background Color is Removed After Being Selected

I have a WPF DataGrid where the row changes color when a checkbox in the row is selected. I have a problem where if a row is highlighted (such as being clicked on by the mouse) and then the DataGrid loses focus then the row loses it's custom color.
Here is were the custom color is set
<Style x:Key="DataGridStyle" TargetType="{x:Type DataGrid}">
<Setter Property="RowStyle">
<Setter.Value>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="#CBE5F2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
Pictures of the problem:
Row is highlighted with mouse:
After DataGrid loses focus
Question:
Is there a way to have the highlighted row keep it's custom color after the DataGrid loses focus.
I found a work around which is to set the cell style instead of the row style:
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="#CBE5F2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
It overrides the selected highlighting (bright blue) completely, so it's not ideal, but it works even after losing focus.

Resources