I need my ToggleMenuFlyout occupy the full screen (on my mobile) but I am not able to.
Someone can help me?
My code:
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>
Thanks
<AppBarButton>
<AppBarButton.Flyout >
<MenuFlyout Placement="Full"></MenuFlyout>
</AppBarButton.Flyout>
</AppBarButton>
Best of luck !
Related
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);
}
I have created a subclass of TextBox
public class MyAwesomeTextBox : TextBox { ... }
and have set the color of all TextBoxes to be red
<UserControl>
<UserControl.Resources>
<Style TargetType="TextBox">
<Setter Property="Background" Value="Red" />
</Style>
</UserControl.Resources>
<TextBox ... />
<xyz:MyAwesomeTextBox ... />
</UserControl>
It works for all TextBoxes but not for MyAwesomeTextBoxes.
Please tell me what is wrong.
I bet you set the DefaultStyleKey property to typeof(MyAwesomeTextBox) and now the framework will only apply a style with the specialized stylekey.
See the documentation, I extracted the following part:
If you do not set the DefaultStyleKey, the default style for the base class is used. For example, if a control called NewButton inherits from Button, to use a new default Style, set DefaultStyleKey to the type, NewButton. If you do not set DefaultStyleKey, the Style for Button is used.
So what can you do now? You can either remove the defaultStyleKey (but that means the TextBox style will be applied everywhere in your application and you cannot have you AwesomeControlTemplate applied to it by default, so I think this is not what you should do now) or you can add a derived style to your resources:
<UserControl.Resources>
<Style TargetType="TextBox" x:Key="BaseStyle">
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}">
<Style TargetType="MyAwesomeTextBox" BasedOn="{StaticResource BaseStyle}">
</UserControl.Resources>
I'm looking to show a dynamic number of buttons in a horizontal way, so that they always fill up the space horizontally no matter how many items.
For example, when there are two button
__________________________________
| other controls |
| |
|________________________________|
| Button 1 | Button 2 | Button 3 |
----------------------------------
and button 2 gets hidden(collapsed), this should become
__________________________________
| other controls |
| |
|________________________________|
| Button 1 | Button 3 |
----------------------------------
Is this possible with Winrt/WP 8.1 xaml?
I would work with a Grid and set the column width to zero in order to hide it. Since all other columns have star values they should stretch accordingly. If everything fails you can recalculate the star values manually since you know the number of visible buttons.
Sample:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Foo" Margin="0,0,0,0" HorizontalAlignment="Stretch" />
<Button Grid.Column="1" Content="Foo" Margin="0,0,0,0" HorizontalAlignment="Stretch" />
<Button Grid.Column="2" Content="Foo" Margin="0,0,0,0" HorizontalAlignment="Stretch" />
</Grid>
Set the ColumnDefinition of one column to zero and the button is hidden and the other columns adjust accordingly.
You can always provide your own custom layout logic by deriving from Panel. Here's what I came up with:
StretchPanel.cs
class StretchPanel : Panel
{
#region Properties
public bool EqualWidths
{
get { return (bool)GetValue(EqualWidthsProperty); }
set { SetValue(EqualWidthsProperty, value); }
}
public static readonly DependencyProperty EqualWidthsProperty =
DependencyProperty.Register("EqualWidths", typeof(bool), typeof(StretchPanel), new PropertyMetadata(false, onEqualWidthsChanged));
#endregion
static void onEqualWidthsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var panel = (StretchPanel)d;
panel.InvalidateMeasure();
panel.InvalidateArrange();
}
protected override Size MeasureOverride(Size availableSize)
{
var renderedChildren = Children.Where(c => c.Visibility == Visibility.Visible);
var count = renderedChildren.Count();
Size childAvailableSize = availableSize;
if (EqualWidths)
childAvailableSize = new Size(availableSize.Width / count, availableSize.Height);
foreach (var child in renderedChildren)
child.Measure(childAvailableSize);
var totalHeight = renderedChildren.Max(c => c.DesiredSize.Height);
return new Size(availableSize.Width, totalHeight);
}
protected override Size ArrangeOverride(Size finalSize)
{
var renderedChildren = Children.Where(c => c.Visibility == Visibility.Visible);
var count = renderedChildren.Count();
var equalWidth = finalSize.Width / count;
var totalWidth = renderedChildren.Sum(c => c.DesiredSize.Width);
var totalHeight = renderedChildren.Max(c => c.DesiredSize.Height);
var x = 0.0;
foreach (var child in renderedChildren)
{
var r = new Rect();
r.X = x;
r.Y = 0;
r.Width = EqualWidths ? equalWidth : child.DesiredSize.Width / totalWidth * finalSize.Width;
r.Height = child.DesiredSize.Height;
child.Arrange(r);
x += r.Width;
}
return new Size(finalSize.Width, totalHeight);
}
}
You can use it like so:
<Page
x:Class="App19.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App19"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<Style TargetType="Button">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="MinWidth" Value="0" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value="Yellow" />
<Setter Property="Margin" Value="0,10,0,0" />
</Style>
</Page.Resources>
<StackPanel>
<TextBlock>Different widths</TextBlock>
<local:StretchPanel EqualWidths="False">
<Button>a</Button>
<Button>big</Button>
<Button>purple</Button>
<Button>dishwasher</Button>
</local:StretchPanel>
<TextBlock>Equal widths</TextBlock>
<local:StretchPanel EqualWidths="True">
<Button>a</Button>
<Button>big</Button>
<Button>purple</Button>
<Button>dishwasher</Button>
</local:StretchPanel>
<TextBlock>Different widths, one child hidden</TextBlock>
<local:StretchPanel EqualWidths="False">
<Button>a</Button>
<Button>big</Button>
<Button Visibility="Collapsed">purple</Button>
<Button>dishwasher</Button>
</local:StretchPanel>
<TextBlock>Equal widths, one child hidden</TextBlock>
<local:StretchPanel EqualWidths="True">
<Button>a</Button>
<Button>big</Button>
<Button Visibility="Collapsed">purple</Button>
<Button>dishwasher</Button>
</local:StretchPanel>
</StackPanel>
</Page>
And a screenshot: