I need the items in a ToogleMenuFlyout occupy the full width of the screen.
But I'm not solve the problem.
I'm trying to put the width of my Grid (Grid Main page) but I do not get to do in code-behind.
I am applying a style to MenuFlyoutPresenterStyle but also not to give.
my code is:
AppBarButton x:Name="FiltersPhone" Icon="Filter" Label="Names">
<AppBarButton.Flyout>
<MenuFlyout>
<MenuFlyout.MenuFlyoutPresenterStyle>
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0,4,0,0"/>
</Style>
</MenuFlyout.MenuFlyoutPresenterStyle>
<ToggleMenuFlyoutItem x:Name="FlyoutItemDate" Text="Today" Tag="Date"
IsChecked="True/>
</MenuFlyout>
</AppBarButton.Flyout>
</AppBarButton>
Apply the following should help [Updated to support landscape]:
Note that: this is still not a perfect solution to meet all your requirement. I am just trying to let you understand the MenuFlyoutPresenter's Maxwidth and the ToggleMenuFlyoutItem's width properties are the key to impelement what you want.
Set x:Name = "rootGrid" to page's root grid
In code-behind, implement the following:
public Page2()
{
this.InitializeComponent();
this.Loaded += Page2_Loaded;
}
private void Page2_Loaded(object sender, RoutedEventArgs e)
{
FlyoutItemDate.Width = rootGrid.ActualWidth;
DisplayInformation di = DisplayInformation.GetForCurrentView();
di.OrientationChanged += Di_OrientationChanged;
}
private void Di_OrientationChanged(DisplayInformation sender, object args)
{
if (sender.CurrentOrientation == DisplayOrientations.Portrait)
{
FlyoutItemDate.Width = rootGrid.ActualWidth;
}
else if(sender.CurrentOrientation == DisplayOrientations.Landscape)
{
FlyoutItemDate.Width = rootGrid.ActualHeight;
}
}
Increase maxwidth of MenuFlyoutPresenter to larger one(like 1000)
<Style TargetType="MenuFlyoutPresenter">
<Setter Property="Background" Value="Red"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0,4,0,0"/>
<Setter Property="MaxWidth" Value="1000"/>
</Style>
Here is the result and I make the background to red to make it clear:
Related
Use this to change the FontSize and save it in App.Current.Resources , works but not the FontColor
App.xaml
<Application.Resources>
<x:Double x:Key="defaultFontSize">14</x:Double>
<Color x:Key="defaultTextColor">#141000</Color>
<Style x:Key="ALabel" TargetType="Label">
<Setter Property="TextColor" Value="{DynamicResource defaultTextColor}" />
<Setter Property="FontSize" Value="{DynamicResource defaultFontSize}" />
<Setter Property="HorizontalOptions" Value="Start" />
<Setter Property="VerticalOptions" Value="Center" />
<Setter Property="Opacity" Value="0.8" />
</Style>
</Application.Resources>
MainPage.xaml
<Label
x:Name="Labeltest3"
Padding="30,0,30,0"
Style="{StaticResource ALabel}"
Text="18" />
MainPage.cs
This works for FontSize , Labeltest3.Text is 18 so FontSize = 18
private void Button_Clicked_2(object sender, EventArgs e)
{
int value = Convert.ToInt32(Labeltest3.Text);
Preferences.Set("FontSize", value);
App.Current.Resources["defaultFontSize"] = Preferences.Get("FontSize", 14);
}
This is not working for TextColor , what am i missing or doing wrong ?
Tryed all kinds of variations with the Hexcode in a Label.Text but no luck.
Not Changing of the TextColor and no saving of the TextColor
private void Button_Clicked_3(object sender, EventArgs e)
{
int value = Convert.ToInt32(Labeltest3.Text);
Preferences.Set("FontSize", value);
App.Current.Resources["defaultFontSize"] = Preferences.Get("FontSize", 14);
Preferences.Set("defaultTextColor", "#ffcc00");
App.Current.Resources["defaultTextColor"] = Preferences.Get("TextColor", "#141000");
}
Found it, this works.
Changed this line
Preferences.Set("defaultTextColor", "#ffcc00");
private void Button_Clicked_3(object sender, EventArgs e)
{
Preferences.Set("FontSize", 8);
App.Current.Resources["defaultFontSize"] = Preferences.Get("FontSize", 14);
Preferences.Set("TextColor", "#ffcc00");
App.Current.Resources["defaultTextColor"] = Preferences.Get("TextColor", "#141000");
}
I have the following XAML code below :
<StackLayout
Grid.Row="2"
Orientation="Horizontal"
VerticalOptions="End"
Margin="0,0,0,20"
Spacing="28">
<Button
x:Name="SignInButton"
Visual="Material"
Padding="5"
Margin="10,0,0,0"
Style="{DynamicResource ButtonSecondary}"
HorizontalOptions="FillAndExpand"
Text="Sign In"
Clicked="SignInButton_Clicked"/>
<Button
x:Name="JoinUsButton"
Visual="Material"
Padding="5"
Margin="0,0,10,0"
Style="{DynamicResource ButtonPrimary}"
HorizontalOptions="FillAndExpand"
VerticalOptions="End"
Text="Join Us"
Clicked="JoinUsButton_Clicked"/>
</StackLayout>
The dynamic resources currently stored in the App.xaml file are as follows :
<Style x:Name="ButtonSecondary" x:Key="ButtonSecondary" TargetType="Button" ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{DynamicResource SecondaryColor}" />
<Setter Property="TextColor"
Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="BorderWidth"
Value="1" />
<Setter Property="BorderColor"
Value="{DynamicResource SecondaryBorderColor}" />
<Setter Property="CornerRadius"
Value="50" />
</Style>
However, when I run the app on iOS the buttons look like the image below.
However, on the android device, the buttons look like the image below :
Cauuse : In iOS , if you want to achieve the effect like the above image which you get in Android , you need to set the CornerRadius as half of its HeightRequest .
Solution
Option 1
If the size of the button is always a fixed value , you just need to set the HeightRequest in the style
<Style x:Name="ButtonSecondary" x:Key="ButtonSecondary" TargetType="Button" ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="{DynamicResource SecondaryColor}" />
<Setter Property="TextColor"
Value="{DynamicResource PrimaryTextColor}" />
<Setter Property="BorderWidth"
Value="1" />
<Setter Property="BorderColor"
Value="{DynamicResource SecondaryBorderColor}" />
<Setter Property="CornerRadius"
Value="25" />
<Setter Property="HeightRequest"
Value="50" /> // double of CornerRadius
</Style>
Option 2 :
If the size of Button will change in runtime , you could use Custom Renderer to set the CornerRadius in iOS platform .
in Forms
create a custom button
public class MyButton:Button
{
}
in iOS
using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using App6;
using App6.iOS;
using System.ComponentModel;
[assembly:ExportRenderer(typeof(MyButton),typeof(MyButtonRenderer))]
namespace App6.iOS
{
public class MyButtonRenderer:ButtonRenderer
{
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(e.PropertyName=="Height")
{
var height = Element.Height;
Control.Layer.MasksToBounds = true;
Control.Layer.BorderColor = UIColor.Black.CGColor;
Control.Layer.CornerRadius = (nfloat)(height / 2.0);
Control.Layer.BorderWidth = (nfloat)0.5;
}
}
}
}
in xaml
<local:MyButton
x:Name="SignInButton"
Visual="Material"
Padding="5"
Margin="10,0,0,0"
Style="{DynamicResource ButtonSecondary}"
HorizontalOptions="FillAndExpand"
Text="Sign In"
/>
While I can't see the exact issue you are seeing with the distortion I do see an inconsistency between platforms. This ultimately comes down to how the individual platforms render the CornerRadius property. Android will limit it to what is visibly sensible (basically half the height/width, whichever is smaller) whereas iOS will just do as you ask.
This image shows on the left what I currently see, the middle is my second solution and the right is my first solution.
My possible solutions are:
Attach a Behavior
public class RoundCornerBehavior : Behavior<Button>
{
protected override void OnAttachedTo(Button button)
{
button.SizeChanged += OnSizeChanged;
base.OnAttachedTo(button);
}
protected override void OnDetachingFrom(Button button)
{
button.SizeChanged -= OnSizeChanged;
base.OnDetachingFrom(button);
}
private void OnSizeChanged(object sender, EventArgs e)
{
var button = (Button) sender;
button.CornerRadius = (int)Math.Min(button.Width, button.Height) / 2;
}
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(RoundCornerBehavior), false, propertyChanged: OnAttachBehaviorChanged);
public static bool GetAttachBehavior(BindableObject view)
{
return (bool)view.GetValue(AttachBehaviorProperty);
}
public static void SetAttachBehavior(BindableObject view, bool value)
{
view.SetValue(AttachBehaviorProperty, value);
}
static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
{
if (!(view is Button button))
{
return;
}
var attachBehavior = (bool)newValue;
if (attachBehavior)
{
button.Behaviors.Add(new RoundCornerBehavior());
}
else
{
var toRemove = button.Behaviors.FirstOrDefault(b => b is RoundCornerBehavior);
if (toRemove != null)
{
button.Behaviors.Remove(toRemove);
}
}
}
}
Then simply attach in your style:
<Setter Property="roundButton:RoundCornerBehavior.AttachBehavior" Value="true" />
I would suggest writing some kind of Behavior to provide the sensible CornerRadius which would essentially take the Width and Height properties of the control and simply set the CornerRadius to half the smallest value. I will see if I can knock something up to provide a concrete example shortly.
The nice result of this approach will allow you to continue to define the controls as you were previously and keep the logic self contained in the attached behavior.
Sub class button
An alternative would be to sub class Button and created your own RoundedButton that could do the same as the Behavior approach. Then
public class RoundedButton : Button
{
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
this.CornerRadius = (int)Math.Min(width, height) / 2;
}
}
I'm currently stuck with a problem. I want to declare a eventriggerbehavior for all my listviews. this is my code:
<Style TargetType="ListView">
<Setter Property="ItemTemplate" Value="{StaticResource itemShowTemplate}" />
<i:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="ItemClicked">
<Interactions:InvokeCommandAction Command="{Binding ShowItemClickedCommand}" />
</Interactions:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Style>
the problem I have now is that EventTriggerBehavior is looking for the event on Style and not the targettype of Listview. And the only property left to set on EventTriggerBehavior is SourceObject. But I don't want this behavior on 1 listview, I want it on al my listviews.
Is there a way todo this?
My first idea was that it could work this way:
<Style TargetType="Button">
<Setter Property="i:Interaction.Behaviors">
<Setter.Value>
<i:BehaviorCollection>
<core:EventTriggerBehavior EventName="Click">
<core:InvokeCommandAction Command="{Binding TestCommand}" />
</core:EventTriggerBehavior>
</i:BehaviorCollection>
</Setter.Value>
</Setter>
</Style>
But unfortunately this works only for the first control which gets the behavior attached. The reason is that the value is constructed just once and the AssociatedObject property of the BehaviorCollection is set to the first control.
I have then come over this solution - How to add a Blend Behavior in a Style Setter .
The idea is to create an attached property that manually assigns the behavior to the control.
Based on this I suggest you do it like this:
public static class ListViewBehaviorAttacher
{
public static readonly DependencyProperty IsAttachedProperty = DependencyProperty.RegisterAttached(
"IsAttached", typeof(bool), typeof(ListViewBehaviorAttacher), new PropertyMetadata(default(bool), IsAttachedChanged));
private static void IsAttachedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var listView = (ListView)dependencyObject;
//create the binding
BehaviorCollection collection = new BehaviorCollection();
var eventTrigger = new EventTriggerBehavior() { EventName = "ItemClick" };
var invokeCommandAction = new InvokeCommandAction();
//binding to command
BindingOperations.SetBinding(
invokeCommandAction,
InvokeCommandAction.CommandProperty,
new Binding() { Path = new PropertyPath("ShowItemClickedCommand"), Source = listView.DataContext });
eventTrigger.Actions.Add(invokeCommandAction);
collection.Add(eventTrigger);
listView.SetValue(Interaction.BehaviorsProperty, collection);
}
public static void SetIsAttached(DependencyObject element, bool value)
{
element.SetValue(IsAttachedProperty, value);
}
public static bool GetIsAttached(DependencyObject element)
{
return (bool)element.GetValue(IsAttachedProperty);
}
}
And then in the style attach it like this:
<Style TargetType="ListView">
<Setter Property="SelectionMode" Value="None"></Setter>
<Setter Property="IsItemClickEnabled" Value="True" />
<Setter Property="local:ListViewBehaviorAttacher.IsAttached" Value="True" />
</Style>
<Button ToolTip="Duplicate" ToolTipService.ShowOnDisabled="True"
Command="{Binding Path=DuplicateEntityCommand }"
CommandParameter="{Binding ElementName=GridView, Path=SelectedItems}">
<Image Style="{StaticResource toolbarImageStyle}" Source="/OnePlanner;component/Resources/Icons/duplicate.png"></Image>
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=RadGridView, Path=SelectedItems.Count}" Value="1"/>
<Condition Binding="{Binding Path=IsItemListConstainsToyota}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
The button is tied with the GridView. I have to enable this button based on the selection in SelectedItems. If one selects only one items in the grid and that item does not has let say a string with value equal to Toyota, then the button should be enabled.
I have created a method in viewmodel that I use with commandParameter.
private bool IsItemListConstainsToyota(IList<object> itemList)
{
if (itemList.First() is CarList)
{
String carName= ((CarList)itemList.First()).carNameAsString;
if (carName.Equals("Toyota"))
{
return true;
}
}
return false;
}
The code so far I have does not work. Is there anyway to do in XAML or I have to do it in viewModel?
For the Duplicate Entity Command, you can pass Action<object> for CanExecuteAction. If this is false, then your button will be disabled. Try passing the following Action<object> to the CanExecuteParameter in ICommand.
itemList =>
{
return IsItemListConstainsToyota(itemList);
}
So I have a TextBlock-element in my Windows 8 app which I override the foreground color of like this:
TestTextBlock.Foreground = new SolidColorBrush(Color.FromArgb(255,255,0,0));
I would like to override this color at a later point using a style with a different Foreground-color. Style:
<Style TargetType="TextBlock" x:Key="MyStyle">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
Override:
TestTextBlock.Style = (Style) App.Current.Resources["MyStyle"];
Now this works if I don't initialize the Foreground-property first. It seems as if Foreground has precedence over Style. Thing is this is a simplified example and I can't remove the code line setting the Foreground-property.
Any other way of working around this? I tried setting Foreground = null, but that resulted in invisible text.
You can set your default color however you want, then personally I run a ColorAnimation at it via Storyboard like;
<Storyboard x:Key="ChangeThatForegroundColor">
<ColorAnimation Duration="0"
Storyboard.TargetName="YourTextBlockName"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
To="Yellow" />
</Storyboard>
and you can fire it off with the BeginStoryboard method. Hope this helps.
hope this help :it works for me
<TextBlock x:Name="TestTextBlock" Text="Hello world"/>
1)override SolidColorBrush with solidcolorbrush only
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
TestTextBlock.Foreground = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0));
TestTextBlock.Foreground = new SolidColorBrush(Colors.Yellow);
}
2)override style with style only
<Style x:Key="MyStyle" TargetType="TextBlock" >
<Setter Property="Foreground" Value="Red"/>
</Style>
<Style x:Key="MyStyle1" TargetType="TextBlock" >
<Setter Property="Foreground" Value="Yellow"/>
</Style>
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
TestTextBlock.Style = (Style)App.Current.Resources["MyStyle"];
TestTextBlock.Style = (Style)App.Current.Resources["MyStyle1"];
}