Change the button pointer entered event in UWP using Interactivity - xaml

I want to change the background color when the pointer enter in to the button.So I add the references Interactivity and Core. And my code is:
<Button Name="clickbutton" Height="60" Width="150" VerticalAlignment="Center" Content="ClickButton" Margin="150,20,0,0" Foreground="Black" Background="Bisque" ClickMode="Pres
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding PointerEnteredEvent ,ElementName=clickbutton}" Value="True">
<Core:ChangePropertyAction PropertyName="Background" Value="Green"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
But I didn't saw any changes in the run time. Is there any problem in my code??

You are using a DataTriggerBehavior, which is inappropriate here. Use EventTriggerBehavior instead, which triggers when an event is fired (put the name of event into the EventName property without any suffixes).
<Core:EventTriggerBehavior EventName="PointerEntered">
<Core:ChangePropertyAction PropertyName="Background" Value="Green"/>
</Core:DataTriggerBehavior>
If you want that the background of the button to become Green immediately on mouse enter, change the EventName to PointerMoved.
But I would recommend changing the Button's default template in order to achieve this.

Related

Create a Radio Button group using standard buttons

The idea here is simple, I've got 2 or more buttons and want to have them act like Radio Buttons. So only one can be checked at any time, and when one is checked the others must uncheck themselves. I'm using MVVM so don't want to go down the route of code behind although it would have been easier for this.
Here is the XAML I've tried which locks up due to the buttons referencing each other.
<Label Text="Group Header Sorting" TextColor="{DynamicResource InverseTextColor}"/>
<StackLayout Orientation="Horizontal" Spacing="0">
<buttons:SfButton x:Name="GroupHeaderSortAscButton" Text="Ascending" HeightRequest="35" WidthRequest="90" IsChecked="{Binding Source={x:Reference GroupHeaderSortDescButton}, Path=IsChecked, Converter={converters:InverseBoolConverter}}">
</buttons:SfButton>
<buttons:SfButton x:Name="GroupHeaderSortDescButton" Text="Descending" HeightRequest="35" WidthRequest="90" IsChecked="{Binding Source={x:Reference GroupHeaderSortAscButton}, Path=IsChecked, Converter={converters:InverseBoolConverter}}">
</buttons:SfButton>
</StackLayout>
I've also tried Data Triggers with more success but its still not perfect as it requires the unselected button pressed twice before it starts work.
<StackLayout Orientation="Horizontal" Spacing="0">
<buttons:SfButton x:Name="GroupHeaderSortAscButton" Text="Ascending" HeightRequest="35" WidthRequest="90" IsChecked="False">
<buttons:SfButton.Triggers>
<DataTrigger TargetType="buttons:SfButton" Binding="{Binding Source={x:Reference GroupHeaderSortDescButton}, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
<DataTrigger TargetType="buttons:SfButton" Binding="{Binding Source={x:Reference GroupHeaderSortDescButton}, Path=IsChecked}" Value="False">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</buttons:SfButton.Triggers>
</buttons:SfButton>
<buttons:SfButton x:Name="GroupHeaderSortDescButton" Text="Descending" HeightRequest="35" WidthRequest="90" IsChecked="True">
<buttons:SfButton.Triggers>
<DataTrigger TargetType="buttons:SfButton" Binding="{Binding Source={x:Reference GroupHeaderSortAscButton}, Path=IsChecked}" Value="True">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
<DataTrigger TargetType="buttons:SfButton" Binding="{Binding Source={x:Reference GroupHeaderSortAscButton}, Path=IsChecked}" Value="False">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
</buttons:SfButton.Triggers>
</buttons:SfButton>
</StackLayout>
I'm aware that from XF 4.6 they introduced the RadioButton control, I've tried this and its buggy and according to comments on Git Hub it will have major changes in XF 5, so I don't want to implement this experimental version.
This is the look I'm after:
We have achieved your requirement by using Syncfusion SfButton. To make it as toggle type, need to set the IsCheckable property as True. Then only it will update the IsChecked property properly. To maintain the single selection, we have extended the SfButton by including the GroupKey internal with further validation.
CustomRadioButton
I wanted to be able to do this using standard buttons and XAML and avoid 3rd party controls, nothing more nothing less.
I ended up using Syncfusion's SfSegmentedControl which works rather well, but this is a paid for, 3rd party control.

why ButtonPressedBackgroundThemeBrush is not working for button

Whenever I press and hold the button I can see a blue color background till I release the button
I tried to reset it white by using the key ButtonPressedBackgroundThemeBrush
Here is my button code
<Button Content="Submit" BorderThickness="0" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1" FontSize="21" Height="85" BorderBrush="White" Command="{Binding testCommand}" Foreground="{StaticResource Green}">
<Button.Resources>
<SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="White" />
</Button.Resources>
</Button>
But its not working for some reason.
Try defining the brush in your application resources:
<Application.Resources>
<SolidColorBrush x:Key="ButtonPressedBackgroundThemeBrush" Color="White" />
</Application.Resources>
This will change the button press background for ALL buttons however. If you want specific buttons to have different backgrounds, you'll need to edit the Button template for each. One simple way to do that is to define a style for each and set the Background to whatever you like during the IsPressed Trigger
<Button>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Getting a value from a higher databinding path

I have an object that contains a control defined in a control template, and an object which it gets notifications from.
These notification object keeps track of the status of the object, which translates on the screen to the colour in this instance, although they are used in other areas of the UI to reflect the state of these objects.
The rectangle colour changes fine on the status change, but I have another property which provides the foreground colour of the text.
However, because of the ContentPresenter getting the text from the control, I can no longer get the foreground colour with the TextBlock.Foreground setter in the style, as the binding is pointing elsewhere.
I could put the name of the object in the notification object as well which would get rid of this question and problem, but I have run up against a similar issue in other places, and as I am new to WPF would like to know the way to do it.
This is the main relevant part of the ControlTemplate 'AnimatedTemplate':
<Rectangle x:Name="ColourFill" Stroke="White" RadiusX="5" RadiusY="5">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Path=FillColour}"/>
</Rectangle.Fill>
<Rectangle.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Active}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard> ... </BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="2"
TextBlock.FontFamily="Segoe UI"
TextBlock.FontWeight="Bold">
<ContentPresenter.Style>
<Style>
<Setter Property="TextBlock.FontSize"
Value="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent},
Converter={StaticResource PushPinContentSizeConverter}}" />
<Setter Property="TextBlock.Foreground"
Value="{Binding Path=TextColour}"/>
</Style>
</ContentPresenter.Style>
</ContentPresenter>
this is created with:
ControlTemplate template = (ControlTemplate)_window.FindResource("AnimatedTemplate");
Control c = new ContentControl();
c.Template = template;
c.SetValue(ContentControl.ContentProperty, displayName);
c.DataContext = <the notification object referred to as the first binding>
_window.d1overlay.Children.Add(c);

How to animate HubSection when visibility changed in WinRT Hub Control

I have a HubSection that is dynamically shown/hidden using Visibility Collapsed/Visible during runtime. I would like to animate the HubSection by having it expand and shrink instead of just instantly showing or hiding it.
Animations in WinRT tend to be a science, and I haven't found a good method yet.
If someone could help with a code snippet I would appreciate it. I would prefer to keep it to XAML if possible, rather than putting the animation in a code-behind. Thanks!
Assuming that the visibiity of the hubsection is controlled by a boolean property of a viewmodel, bound through a converter then the solution is simpler than I thought. Even if this is not the case I'm sure you can modify the solution below easily.
You will need to reference the Behaviors SDK for this to work. You can do that either by going to References>Add Reference>Windows 8.1>Extensions>Behaviors SDK or by opening your project in blend and dragging a DataTriggerBehavior on yor hubsection.
Necessary xmlns declarations
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
xmlns:Media="using:Microsoft.Xaml.Interactions.Media"
<Page.Resources>
<Converters:BoolToVisConverter x:Key="BoolToVisConverter"/>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True" Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="hubSection">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="400"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Hub Header="Hub">
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior/>
</Interactivity:Interaction.Behaviors>
<HubSection Header="HubSection 0">
<DataTemplate>
<Grid/>
</DataTemplate>
</HubSection>
<HubSection x:Name="hubSection" Header="HubSection 1" Visibility="{Binding MyProperty, Converter={StaticResource BoolToVisConverter}}" Width="400" Background="#FFB02626">
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding MyProperty}" Value="True">
<Media:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<DataTemplate>
<Grid/>
</DataTemplate>
</HubSection>
</Hub>
<ToggleSwitch Header="ToggleSwitch" HorizontalAlignment="Left" Margin="824,249,0,0" VerticalAlignment="Top" IsOn="{Binding MyProperty, Mode=TwoWay}"/>
The xaml defines a hub with 2 hubsections a toggleswitch to manipulate the boolean property in the viewmodel and a storyboard to animate the second hubsection.
The trick is to use a DataTriggerBehavior instead of an EventTriggerBehavior.
You can even bind directly to the visibility property of the hubsection for the DataTriggerBevavior if you want.

DataTrigger from interaction not working Windows Phone

I have simple example and databinding using TemplatedParent is not working. Does anyone have idea what is wrong?
<Button Background="Red" Content="xD">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border>
<i:Interaction.Triggers>
<ec:DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Background}" Value="Red">
<ec:ChangePropertyAction PropertyName="Background" Value="CadetBlue"/>
</ec:DataTrigger>
</i:Interaction.Triggers>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
No error in output. Background is supposed to be set to CadetBlue but no effect is applied.
It seems that RelativeSource.TemplatedParent works fine inside a template, but the triggers don't work as expected: if the trigger condition matches initially, the trigger/action doesn't fire. If you change the bound property programmatically, the trigger will fire. That's why it works with IsPressed: the button didn't start out pressed; it was pressed after it was loaded.
If you move the triggers out of the template and attach them directly to the button and adjust the bindings accordingly, everything should just work:
<Button x:Name="_button"
Background="Red"
Content="xD">
<i:Interaction.Triggers>
<ei:DataTrigger Binding="{Binding ElementName=_button, Path=Background.Color}"
Value="Red">
<ei:ChangePropertyAction PropertyName="Background"
Value="CadetBlue" />
</ei:DataTrigger>
</i:Interaction.Triggers>
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
Note the background trigger must bind to Background.Color; it doesn't work if you bind to the brush itself, possibly because SolidColorBrush does not override Equals.