Styling WPF toolkit datagrid - datagrid

I hope to find an answer on customizing Datagrid from WPF toolkit 2010. I'd like to add a TITLE area to be above DataGridColumnHeaderPresenter of the datagrid. The problem is that I want it to be as a user control or data template where I can populate the title from XML. I want to have unique titles for multiple datagrids on one page getting data from one XML. I populate few datagrids in the same window. What will be the best solution to add customizable Tile area for a content populated from XML and bounded to each datagrid to avoid dublication?
Thank you in advance. I generate datagrid with columns this way:
<Custom:DataGrid Grid.Column="0" Grid.Row="1" x:Name="ServerList" ItemsSource="{Binding Source={StaticResource PagesData}, XPath=ListTiles/Tile1}">
<Custom:DataGrid.Columns>
<Custom:DataGridTextColumn Header="Name" Binding="{Binding XPath=#Name}" />
<Custom:DataGridTextColumn Header="Status" Binding="{Binding XPath=#Status}" />
<Custom:DataGridTextColumn Header="Events" Binding="{Binding XPath=#Events}" />
<Custom:DataGridTextColumn Header="Services" Binding="{Binding XPath=#Services}" />
</Custom:DataGrid.Columns>
<Custom:DataGrid x:Name="Events" Grid.Column="0" Grid.Row="2" ItemsSource="{Binding Source={StaticResource PagesData}, XPath=ListTiles/Tile2}" >
<Custom:DataGrid.Columns>
<Custom:DataGridTextColumn Header="Name" Binding="{Binding XPath=#Name}" />
<Custom:DataGridTextColumn Header="Level" Binding="{Binding XPath=#Level}" />
<Custom:DataGridTextColumn Header="Source" Binding="{Binding XPath=#Source}" />
<Custom:DataGridTextColumn Header="In last 24h" Binding="{Binding XPath=#TimeSpan}" />
</Custom:DataGrid.Columns>
<Custom:DataGrid x:Name="Services" Grid.Column="2" Grid.Row="2" ItemsSource="{Binding Source={StaticResource PagesData}, XPath=ListTiles/Tile3}">
<Custom:DataGrid.Columns>
<Custom:DataGridTextColumn Header="Name" Binding="{Binding XPath=#Name}" />
<Custom:DataGridTextColumn Header="Status" Binding="{Binding XPath=#Status}" />
<Custom:DataGridTextColumn Header="Start" Binding="{Binding XPath=#Start}" />
</Custom:DataGrid.Columns>
XML:
<?xml version="1.0" encoding="utf-8"?>
<ListTiles xmlns="">
<Tile1>
<Header Title="ROLES & GROUPS" />
<Server Name="Kim" Status="ready" Events="1" Services="1" />
<Server Name="Sherri" Status="past" Events="2" Services="1"/>
<Server Name="Mike" Status="future" Events="3" Services="1" />
</Tile1>
<Tile2>
<Header Title="EVENTS" />
<Server Name="Young" Level="average" Source="home" TimeSpan="5" />
<Server Name="Sarah" Level="Critical" Source="work" TimeSpan="6" />
<Server Name="Susan" Level="normal" Source="friend" TimeSpan="2" />
</Tile2>
<Tile3>
<Header Title="SERVICES" />
<Server Name="Josh" DisplayName="FF" Status="Running" Start="Auto" />
<Server Name="Amy" DisplayName="DD" Status="Rest" Start="Auto" />
<Server Name="Bill" DisplayName="AS" Status="Work" Start="Auto" />
</Tile3>
</ListTiles>

Related

Xamarin Forms IsEnabled MultiTrigger on Entry is not working

I am trying to get an entry IsEnabled property to set based on 2 different boolean values using a MultiTrigger in Xamarin.Forms 4.6.0.726. I have also tried in the last stable 4.5 version too.
Unfortunately the Entry IsEnabled property seems to remain at whatever the Setter's value is set to (in the case, true).
I have tried the two types of BindingCondition in the below code sample. The first (uncommented) conditions are bound to the IsVisible properties of two other elements on the page. The StackLayout and the Image will toggle their visibility as expected, however the Entry IsEnabled will not changed.
The second snip of code binds directly to the values in the ViewModel, implenenting INotifyPropertyChanged but has the exact same result where the IsEnabled value does not change.
I have run out of ideas and i'm starting to wonder if this is a bug with Xamarin and MultiTriggers. There doesn't seem to be a huge amount of people using them online, and those that do I have mine set out in what seems to be the most common way in the first set of code.
<StackLayout x:Name="ButtonsStack" IsVisible="{Binding Invoice.Editable}">
<!-- Content Here -->
</StackLayout>
<Image x:Name="InvoiceImage" IsVisible="{Binding IsUploadInvoice}" />
<StackLayout Orientation="Horizontal" HorizontalOptions="End">
<Entry Text="{Binding Invoice.TotalAmount}">
<Entry.Triggers>
<MultiTrigger TargetType="Entry">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference ButtonsStack}, Path=IsVisible}" Value="True"/>
<BindingCondition Binding="{Binding Source={x:Reference InvoiceImage}, Path=IsVisible}" Value="True"/>
<!--<BindingCondition Binding="{Binding Invoice.Editable}" Value="True"/>
<BindingCondition Binding="{Binding IsUploadInvoice}" Value="True"/>-->
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiTrigger>
<Entry.Triggers>
<Entry>
</StackLayout>
As zafar said, you need to set Entry IsEnable="False" by default, when all the conditions are true, the setter makes the Entry's IsEnabled property true.
<StackLayout>
<Entry IsEnabled="False" Text="{Binding Invoice.TotalAmount}">
<Entry.Triggers>
<MultiTrigger TargetType="Entry">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference ButtonsStack}, Path=IsVisible}" Value="True" />
<BindingCondition Binding="{Binding Source={x:Reference InvoiceImage}, Path=IsVisible}" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiTrigger>
</Entry.Triggers>
</Entry>
</StackLayout>
About Multi triggers, please take a look:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/triggers

Attach DataTemplate to Xamarin.Forms ShellContent

I'm succesfully attaching a DataTemplate to my FlyoutItems and MenuItems in my Xamarin.Forms Shell App. However, how do I attach the same template to the ShellContent?
<?xml version="1.0" encoding="UTF-8"?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MyApp.Views"
xmlns:volDash="clr-namespace:MyApp.Views.VolDash"
xmlns:orgDash="clr-namespace:MyApp.Views.OrgDash"
x:Class="EventingVolunteers.AppShell"
FlyoutBackgroundColor="#337ab7">
<Shell.Resources>
<Style x:Key="FlyoutItemStyle" TargetType="Grid">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Red"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Green"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<DataTemplate x:Key="FlyoutTemplates">
<Grid HeightRequest="{x:OnPlatform Android=50}" Style="{StaticResource FlyoutItemStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{x:OnPlatform Android=54, iOS=50}"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="{Binding FlyoutIcon}"
VerticalOptions="Center"
HorizontalOptions="Center"
HeightRequest="{x:OnPlatform Android=24, iOS=22}"
WidthRequest="{x:OnPlatform Android=24, iOS=22}">
</Image>
<Label VerticalOptions="Center"
Text="{Binding Title}"
FontSize="{x:OnPlatform Android=14, iOS=Small}"
FontAttributes="Bold" Grid.Column="1">
<Label.TextColor>
White
</Label.TextColor>
<Label.Margin>
<OnPlatform x:TypeArguments="Thickness">
<OnPlatform.Platforms>
<On Platform="Android" Value="20, 0, 0, 0" />
</OnPlatform.Platforms>
</OnPlatform>
</Label.Margin>
<Label.FontFamily>
<OnPlatform x:TypeArguments="x:String">
<OnPlatform.Platforms>
<On Platform="Android" Value="sans-serif-medium" />
</OnPlatform.Platforms>
</OnPlatform>
</Label.FontFamily>
</Label>
</Grid>
</DataTemplate>
</Shell.Resources>
<FlyoutItem
x:Name="volFlyoutItem"
Title="Volunteer Dashboard"
FlyoutDisplayOptions="AsSingleItem"
FlyoutIcon="ic_dashboard_white.png"
Shell.ItemTemplate="{StaticResource FlyoutTemplates}">
<ShellContent Title="Signups" Icon="ic_assignment.png">
<volDash:SignupsPage />
</ShellContent>
<ShellContent Title="Events" Icon="ic_event.png">
<volDash:AreasPage />
</ShellContent>
<ShellContent Title="Mailbox" Icon="ic_mail_outline.png">
<volDash:MailboxPage />
</ShellContent>
<ShellContent Title="Rankings" Icon="fa_trophy.png">
<volDash:MyRankingsPage />
</ShellContent>
<ShellContent Title="Videos" Icon="ic_ondemand_video.png">
<volDash:TrainingVideoCategoriesPage />
</ShellContent>
</FlyoutItem>
<FlyoutItem
x:Name="orgFlyoutItem"
Title="Organizer Dashboard"
FlyoutDisplayOptions="AsSingleItem"
FlyoutIcon="ic_dashboard_white.png"
IsEnabled="False"
Shell.ItemTemplate="{StaticResource FlyoutTemplates}">
<ShellContent Title="Events" Icon="ic_event.png">
<orgDash:EventsPage />
</ShellContent>
</FlyoutItem>
<ShellContent
Title="Account"
Icon="ic_account_box_white.png"
Shell.ItemTemplate="{StaticResource FlyoutTemplates}"
Shell.MenuItemTemplate="{StaticResource FlyoutTemplates}">
<views:AccountPage />
</ShellContent>
<MenuItem
Shell.MenuItemTemplate="{StaticResource FlyoutTemplates}"
Text="Logout"
Icon="ic_dashboard_white.png"
Command="{Binding LogOutCommand}" />
</Shell>
Shell has implicit conversion operators that enable the Shell visual hierarchy to be simplified, without introducing additional views into the visual tree. This is possible because a subclassed Shell object can only ever contain FlyoutItem objects or a TabBar object, which can only ever contain Tab objects, which can only ever contain ShellContent objects. These implicit conversion operators can be used to remove the FlyoutItem, Tab, and ShellContent objects.
In your xaml,the ShellContent is a simplification of <FlayoutItme> <ShellContent/></FlayoutItme>,so you just need to add <FlayoutItme> outside it and add Shell.ItemTemplate.
<FlyoutItem
x:Name="account"
Title="Account"
FlyoutDisplayOptions="AsSingleItem"
FlyoutIcon="ic_account_box_white.png"
Shell.ItemTemplate="{StaticResource FlyoutTemplates}">
<ShellContent>
<views:AccountPage />
</ShellContent>
</FlyoutItem>

Xamarin Forms ToolbarItem doesn't change IsEnabled from XAML

I'm facing a problem with ToolbarItem and IsEnabled property when trying to turn it on/off from XAML using triggers. ToolbarItem doesn't support triggers, so what I do is to create a Button (a hidden one) which supports triggers and then bind Button.IsEnabled to ToolbarItem.IsEnabled; here is the sample code:
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="tlbSave" Text="Save" Clicked="Handle_Clicked">
<ToolbarItem.IsEnabled>
<Binding Source="{x:Reference btnTest}" Path="IsEnabled" />
</ToolbarItem.IsEnabled>
</ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Padding="10" VerticalOptions="CenterAndExpand">
<Entry x:Name="txtTest" HorizontalOptions="FillAndExpand" />
<Button x:Name="btnTest" Text="HIDDEN" IsEnabled="false" HorizontalOptions="FillAndExpand">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference txtTest}, Path=Text.Length,
Converter={convert:IsPositiveIntegerConverter}}" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiTrigger>
</Button.Triggers>
</Button>
</StackLayout>
</ContentPage.Content>
If you try this piece of code you will see how btnTest gets enable/disable when txtTest.Text has some value. But it isn't affecting tlbSave.IsEnabled property.
However, this work perfect in code behind when I set tlbSave.IsEnabled into btnText.PropertyChanged EventHandler
btnTest.IsVisible is false, I'm just showing it up for testing purposes.
Any idea about how to deal with this?
This is because of the IsEnabled property of ToolbarItem is read-only.
If you just set IsEnabled property of a toolbar item in your XAML to false or true, you will get the following exception at runtime.
System.InvalidOperationException: The BindableProperty "IsEnabled" is readonly.
And if you take a look at Microsoft's documentation, you will notice that you cannot directly set IsEnabled property of a toolbar item.
For disabling a toolbar item, the suggested way is to use a command and it's CanExecute.
I found out a way to solve this problem, at least a way better than implementing OnPropertyChange for btnTest
<ContentPage.ToolbarItems>
<ToolbarItem x:Name="tlbSave" Text="Save" Clicked="Handle_Clicked" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout Padding="10" VerticalOptions="CenterAndExpand">
<Entry x:Name="txtTest" HorizontalOptions="FillAndExpand" />
<Button x:Name="btnTest" Text="HIDDEN">
<Button.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference txtTest}, Path=Text.Length,
Converter={convert:IsPositiveIntegerConverter}}" Value="true" />
</MultiTrigger.Conditions>
<Setter Property="IsEnabled" Value="True" />
</MultiTrigger>
</Button.Triggers>
<Button.IsEnabled>
<Binding Source="{x:Reference tlbSave}" Path="IsEnabled" Mode="OneWayToSource" />
</Button.IsEnabled>
</Button>
</StackLayout>
</ContentPage.Content>
Then set btnTest.IsEnabled = false; inside constructor and everything will go as smooth as I want.

Is it possible to have a tab inside of a page in XamarinForm?

I typed "tab" and the only thing that seems to be relavent in the IntelliSense was "TabbedPage". I searched Google, and it also only showed tabbed page.
But what if I want something else above the tab? Something like this? Is this achievable in Xamarin Form? It is possible in native Android.
--------------------
Text inputs, buttons
---------------------
tabbed or swipe-able
content
--------------------
TabbedPage is a Page, is not a View so you can't include it inside another page.
On GitHub there is some TabView you can use. For example XFControls
<ctrls:TabView.TabTemplate>
<DataTemplate>
<StackLayout>
<ctrls:FontIcon Glyph="{Binding Glyph}"
FontFamily="{StaticResource font}"
FontSize="25"
Color="Gray"
HorizontalOptions="Center"
>
<ctrls:FontIcon.Triggers>
<DataTrigger TargetType="ctrls:FontIcon"
Binding="{Binding IsSelected}"
Value="True"
>
<Setter Property="Color" Value="Red" />
</DataTrigger>
</ctrls:FontIcon.Triggers>
</ctrls:FontIcon>
<Label Text="{Binding Title}"
TextColor="Gray"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
FontSize="10">
<Label.Triggers>
<DataTrigger TargetType="Label"
Binding="{Binding IsSelected}"
Value="True"
>
<Setter Property="TextColor" Value="Red" />
</DataTrigger>
</Label.Triggers>
</Label>
</StackLayout>
</DataTemplate>
</ctrls:TabView.TabTemplate>
<ctrls:TabView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"
HorizontalOptions="Center" />
</DataTemplate>
</ctrls:TabView.ItemTemplate>
</ctrls:TabView>

xamarin forms get a value from ResourceDictionary

I have 2 different values for the Left Margin and the Right Margin for my application. (Let say 27 and 64)
Is it possible to get these values from the ResourcesDictionaty and set them in my XAML.
For example
<StackLayout Margin="{Left1},0,{Right1},0">
</StackLayout>
You can specify them as double values in ResourceDictionary and refer to them in other resources/styles or at element level itself.
Sample resource-dictionary
<ResourceDictionary>
<!-- namespace declaration
xmlns:sys="clr-namespace:System;assembly=System.Runtime" -->
<sys:Double x:Key="leftMargin">20</sys:Double>
<sys:Double x:Key="rightMargin">30</sys:Double>
<Thickness x:Key="MyMargin1"
Left="{StaticResource leftMargin}"
Right="{StaticResource rightMargin}"
Top="20"
Bottom="30" />
<Thickness x:Key="MyMargin2"
Left="{StaticResource leftMargin}"
Right="{StaticResource rightMargin}"
Top="5"
Bottom="15" />
</ResourceDictionary>
Sample usage
<StackLayout>
<BoxView BackgroundColor="Blue" Margin="{StaticResource MyMargin1}" />
<BoxView HeightRequest="1" BackgroundColor="Black" />
<BoxView BackgroundColor="Red" Margin="{StaticResource MyMargin2}" />
<BoxView HeightRequest="1" BackgroundColor="Black" />
<BoxView BackgroundColor="Yellow">
<BoxView.Margin>
<Thickness
Left="{StaticResource leftMargin}"
Right="{StaticResource rightMargin}"
Top="30"
Bottom="10" />
</BoxView.Margin>
</BoxView>
<BoxView HeightRequest="1" BackgroundColor="Black" />
</StackLayout>
I don't think doing this for individual values will work. You can however bind the entire Margin to a value in a resource dictionary as follows:
<ResourceDictionary>
<Thickness x:Key="MyMargin">27,0,64,0</Thickness>
</ResourceDictionary>
<StackLayout Margin="{StaticResource MyMargin}">
</StackLayout>

Resources