UWP UserControl Resources Binding to x:Bind - c#

In this xaml snippet I tried to specify the ViewModel and the Locator for the x DataType to change the bindings to x:Bind, but unfortunately that doesn't work here. Why can't I simply omit the specification of Source={StaticResource Locator} and address the whole thing via the x DataType, what am I doing wrong?
<DataTemplate x:Key="appointmentTemplate" >
<Grid Background="White" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding CalendarUCView.GridTappedCommand, Source={StaticResource Locator}}"/>
</core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<ListView ItemsSource="{Binding Converter={StaticResource cellModelToEventsConverter}, Mode=TwoWay}"
VerticalAlignment="Top"
Grid.Row="0"
Style="{StaticResource appointmentCellListViewStyle}"
ScrollViewer.VerticalScrollMode="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{Binding CalendarUCView.SelectedAppointment, Source={StaticResource Locator}, Mode=TwoWay}">
<Interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding CalendarUCView.ItemTappedCommand, Source={StaticResource Locator}}"/>
</core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</ListView>
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Grid.Row="1"
Text="{Binding Converter={StaticResource cellModelToDayConverter}, Mode=OneWay}"
Margin="4"/>
</Grid>
</DataTemplate>
I tryed:
<DataTemplate x:Key="appointmentTemplate"
x:DataType="viewModel:CalendarUCViewModel" >
and also:
<DataTemplate x:Key="appointmentTemplate"
x:DataType="locator:CalendarUCView" >
So usually I can do this:
Command="{x:Bind GridTappedCommand}"
instead of that:
Command="{Binding CalendarUCView.GridTappedCommand, Source={StaticResource Locator}}"
Or if I change the x:DataType to the View (x:DataType="local:CalendarUCView") and use in View:
public CalendarUCViewModel Vm
{
get => (CalendarUCViewModel)DataContext;
}
usually can do this:
Command="{x:Bind Vm.GridTappedCommand}"

Related

How to access a page's datacontext from inside a listview?

I am using MVVM Cross to build a UWP application. I am having trouble binding a command to a button. Previously in the XAML page I used an interactivity to bind other commands. The issue here is that we are using a listview to present a user's "favorite list." The UnfavoriteCommand is in the ViewModel but never gets hit because User.Favorite list is in a model and does not have the "UnfavoriteCommand." How do I handle this binding issue using MVVM Cross?
<ListView
Grid.Row="0"
Grid.Column="0"
CanReorderItems="True"
CanDrag="True"
AllowDrop="True"
ItemsSource="{Binding User.FavoriteList}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Grid.Row="0"
HorizontalAlignment="Left"
Margin="0, 0, 0, 0"
Height="25" >
<TextBlock Text="{Binding Description, Mode=TwoWay}"
VerticalAlignment="Center"
TextAlignment="Left"/>
</StackPanel>
<StackPanel VerticalAlignment="Center" Grid.Column="1" Grid.Row="0">
<Button Content=""
FontFamily="{StaticResource FontAwesomeFontFamily}"
BorderBrush="Black">
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:EventTriggerBehavior.Actions>
<Core:InvokeCommandAction CommandParameter="{Binding}" Command="{Binding UnfavoriteCommand}"/>
<!--<Core:CallMethodAction TargetObject="{Binding}" MethodName="Unfavorite" />-->
<!--<Core:InvokeCommandAction Command="{Binding UnfavoriteCommand}" InputConverter="{StaticResource buttonConverter}"/>-->
</Core:EventTriggerBehavior.Actions>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Give your page a name and use ElementName binding.
<Core:InvokeCommandAction CommandParameter="{Binding}" Command="{Binding DataContext.UnfavoriteCommand, ElementName=PageName}"/>
This code is for a wpf applcation but I think it's the same with UWP applications, you should use RelativeSource to reference a distinct source or context, May be you has a ViewModel as (Interface only):
public class IAnyViewModel {
RelayCommand UnfavoriteCommand {get;}
ObservableCollection<UserFavorite> FavoriteList {get;set;}
}
And this class is assigned to page or window controll in constructor or by code some thing like this:
public constructorControl(){
this.DataContext = new AnyViewModel();
}
or by XAML.
<Page.DataContext>
<local:AnyViewModel></local:AnyViewModel>
</Page.DataContext>
Then you can reference to parent context using RelativeSource some like this:
<Core:InvokeCommandAction
Command="{Binding UnfavoriteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}">
I'm Assuming your control is Page.

Using 2 different ViewModels in a Grid

Can you use 2 different ViewModels in a Grid?
One ViewModel to fill a ComboBox and another ViewModel to get the selectedItem?
Like this sample (not working):
<Grid Grid.Row="4"
DataContext="{Binding ViewModel1, Mode=OneWay, Source={StaticResource Locator}}">
<TextBlock Grid.Row="4"
Text="Language:"
FontWeight="Bold"
VerticalAlignment="Center" />
<ComboBox Grid.Column="1"
DisplayMemberPath="Value"
VerticalAlignment="Center"
Width="200"
ItemsSource="{Binding LanguageList}"
DataContext="{Binding ViewModel2, Mode=OneWay, Source={StaticResource Locator}}"
SelectedItem="{Binding SelectedLanguage}"/>
</Grid>
You could specify an explicit source for each binding:
<Grid Grid.Row="4">
<TextBlock Grid.Row="4"
Text="Language:"
FontWeight="Bold"
VerticalAlignment="Center" />
<ComboBox Grid.Column="1"
DisplayMemberPath="Value"
VerticalAlignment="Center"
Width="200"
ItemsSource="{Binding ViewModel1.LanguageList, Source={StaticResource Locator}}"
SelectedItem="{Binding ViewModel2.SelectedLanguage, Source={StaticResource Locator}}"/>
</Grid>

Can't bind a ContextMenu action to a Command

I've searched and read anything I can about ContextMenus and binding, and how it's not in the tree... etc. So searching feels like I've exhausted it and just don't understand it.
I'm trying to get my ContextMenu AddTournamentCommand to work, but I simply can't get it to command. I recently found out the easy way through Data Sources to bind to objects, so if there's an easy way other than coding it by hand to wire it up, please let me know. This is what I have so far:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Models="clr-namespace:FumbblApiClient.Models" mc:Ignorable="d" x:Name="FumbblMainWindow" x:Class="FumbblApiClient.MainWindow"
Title="MainWindow" Height="499.45" Width="639" Loaded="Window_Loaded">
<Window.Resources>
<CollectionViewSource x:Key="groupViewSource" d:DesignSource="{d:DesignInstance {x:Type Models:Group}, CreateList=True}"/>
<CollectionViewSource x:Key="groupTournamentsViewSource" Source="{Binding Tournaments, Source={StaticResource groupViewSource}}"/>
</Window.Resources>
<Grid Margin="0,0,2,0">
<TabControl Margin="10">
<TabItem Header="Groups">
<Grid Background="#FFE5E5E5" DataContext="{StaticResource groupViewSource}">
<TextBox x:Name="GroupIdTextBox" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="Group ID" VerticalAlignment="Top" Width="100" Grid.Column="1"/>
<Button Content="Fetch" HorizontalAlignment="Left" Margin="115,11,0,0" VerticalAlignment="Top" Width="61" Click="GroupFetch_Click" Grid.Column="1" Height="22"/>
<ListBox x:Name="groupListView" ItemsSource="{Binding}" Margin="10,38,0,10" SelectionMode="Single" HorizontalAlignment="Left" Width="166" SelectionChanged="GroupList_SelectionChanged">
</ListBox>
<Grid x:Name="grid1" Margin="181,38,10,0" VerticalAlignment="Top" Height="369">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Id:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
<TextBox x:Name="idTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding Id, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
<Label Content="Name:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="1" VerticalAlignment="Center"/>
<TextBox x:Name="nameTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="1" Text="{Binding Name, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
<Label Content="Tournaments:" HorizontalAlignment="Left" Margin="3" Grid.Row="2" VerticalAlignment="Center"/>
<ListBox x:Name="tournamentsListView" ItemsSource="{Binding Source={StaticResource groupTournamentsViewSource}}" Margin="3,3,-182,-260" SelectionMode="Multiple" Grid.Row="2" Grid.Column="1">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="UIElement.PreviewMouseRightButtonDown" Handler="EmptyHandler"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Add To Selected Tournaments" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=PlacementTarget.DataContext.AddTournamentCommand}"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
</Grid>
</Grid>
</TabItem>
<TabItem Header="Tournaments">
<Grid Background="#FFE5E5E5" Margin="0,0,0,-2">
<ListBox HorizontalAlignment="Left" Margin="10,10,0,10" Width="166"/>
</Grid>
</TabItem>
<TabItem Header="Teams">
</TabItem>
<Grid Margin="0,0,-10,10"/>
</TabControl>
</Grid>
</Window>
and in the Code Behind:
public partial class MainWindow : Window
{
[removed]
private ICommand addTournamentCommand;
public ICommand AddTournamentCommand
{
get
{
if(addTournamentCommand == null)
{
addTournamentCommand = new RelayCommand(OnTournamentAdded);
}
return addTournamentCommand;
}
}
private void OnTournamentAdded(object state)
{
}
}
PlacementTarget property is on Context Menu and not on window. Travel to ContextMenu and not to Window. Window anyhow doesn't lies in Visual Tree of ContextMenu so you can't reach to it using RelativeSource.
<ContextMenu>
<MenuItem Header="Add To Selected Tournaments"
Command="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ContextMenu}},
Path=PlacementTarget.DataContext.AddTournamentCommand}"/>
</ContextMenu>
With above code you will get PlacementTarget's dataContext which will be ListBox's DataContext and if you haven't set explicitly DataContext on ListBox, it will inherit it from Window and your code will work fine.
UPDATE
You can store the Window DataContext in Tag of ListBox and bind with it.
<ListBox Tag="{Binding DataContext,
RelativeSource={RealtiveSource Mode=FindAncestor,
AncestorType=Window}}"/>
and in ContextMenu bind using Tag:
<ContextMenu>
<MenuItem Header="Add To Selected Tournaments"
Command="{Binding RelativeSource={RelativeSource
AncestorType={x:Type ContextMenu}},
Path=PlacementTarget.Tag.AddTournamentCommand}"/>
</ContextMenu>
Change like this,
<ContextMenu>
<MenuItem Header="Add To Selected Tournaments" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=AddTournamentCommand}"/>
</ContextMenu>

Binding event from nested control

I'm writing application in windows phone 8 and have problem with bindings.
Here is my xaml code with my page structure
<phone:Pivot Grid.Row="1" SelectedIndex="{Binding SelectedPivotElement, Mode=TwoWay}" x:Name="SymbolsPivot" Title="Symbols" ItemsSource="{Binding CategoriesWithSymbols}">
<phone:Pivot.HeaderTemplate>
<DataTemplate>
<ContentControl Content="{Binding Name}"/>
</DataTemplate>
</phone:Pivot.HeaderTemplate>
<phone:Pivot.ItemTemplate>
<DataTemplate>
<telerikData:RadJumpList x:Name="SymbolsControl" ItemsSource="{Binding Path=Symbols}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<telerikData:RadJumpList.GroupDescriptors>
<data:PropertyGroupDescriptor PropertyName="GroupName"
SortMode="Ascending" />
</telerikData:RadJumpList.GroupDescriptors>
<telerikPrimitives:RadDataBoundListBox.VirtualizationStrategyDefinition>
<telerikPrimitives:WrapVirtualizationStrategyDefinition Orientation="Horizontal"/>
</telerikPrimitives:RadDataBoundListBox.VirtualizationStrategyDefinition>
<telerikData:RadJumpList.GroupHeaderTemplate>
<DataTemplate>
<Grid Margin="0,-8,0,12" Width="480">
<TextBlock FontWeight="Bold" FontSize="{StaticResource PhoneFontSizeMedium}" Text="{Binding}" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</telerikData:RadJumpList.GroupHeaderTemplate>
<telerikData:RadJumpList.ItemTemplate>
<DataTemplate>
<Grid Width="300">
<TextBlock Text="{Binding Symbol}"/>
</Grid>
</DataTemplate>
</telerikData:RadJumpList.ItemTemplate>
</telerikData:RadJumpList>
</DataTemplate>
</phone:Pivot.ItemTemplate>
</phone:Pivot>
<i:Interaction.Triggers>
<i:EventTrigger EventName="ItemTap" SourceName="SymbolsControl" >
<cmd:EventToCommand Command="{Binding TapCommand}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
So I have pivot control and inside pivot I have a list.
And now the problem is that application binds item tap event to my relay command but this event/command is never called. Everything works if I move list outside pivot. How to fix that problem ?

howto: Column drag/Move functionality in itemscontrol similar to DataGrid in Silverlight

e have a requirement to show vertical profiles of Data related to an entity, the profiles can change dynamically, so basically its a dynamic column grid, just that its not a Grid control, instead i have acheived this using ItemsControl and Listboxes.
Now i need to implement something similar to how the Grid behaves in column moving, i have to be able to move the Profile 6 next to Profile 1 to compare.
How can i achieve this ?
Below is my Xaml that renders the screen as shown below the code.
Header buttons are toggle buttons, so clicking on it selects the whole profile.
Updated Code with Drag and Drop
<ScrollViewer Height="500" Name="scrollViewer1" Width="Auto" HorizontalAlignment="Stretch"
VerticalAlignment="Top" Margin="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<toolkit:DockPanel>
<!-- Items control container to hold time Bucket information -->
<ItemsControl x:Name="TimeBucket" Grid.Column="0" toolkit:DockPanel.Dock="Left" VerticalAlignment="Top">
<Grid HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToggleButton Grid.Row="0" Content="Bucket" Width="Auto" HorizontalAlignment="Stretch" IsEnabled="False"/>
<ListBox Grid.Row="1" Width="Auto" ItemsSource="{Binding Source={StaticResource DC1}, Path=Content.TimeBuckets, Mode=TwoWay}"
IsEnabled="False">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" Style="{StaticResource BucketProfileStyle}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Stretch">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
</Grid>
</ItemsControl>
<!-- Items Control for dynamic profile columns creation -->
<toolkit:ListBoxDragDropTarget AllowDrop="True" AllowedSourceEffects="Move" toolkit:DockPanel.Dock="Left" BorderThickness="0" Padding="0" VerticalAlignment="Top">
<ListBox ItemsSource="{Binding Profiles}" VerticalAlignment="Top" toolkit:DockPanel.Dock="Left" BorderThickness="0" Padding="0" IsTabStop="True" TabNavigation="Cycle">
<!--<ItemsControl x:Name="Profile" ItemsSource="{Binding Profiles}" VerticalAlignment="Top" toolkit:DockPanel.Dock="Left" Drop="Profile_Drop" >-->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Drop="StackPanel_Drop" Margin="0"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ToggleButton Grid.Row="0" x:Name="HeaderButton" Content="{Binding Name}" Tag="{Binding ID}"
Width="Auto" HorizontalAlignment="Stretch" ClickMode="Release">
<i:Interaction.Behaviors>
<b:ToggleButtonAsHeaderButtonItemClickBehavior Command="{Binding Source={StaticResource DC1}, Path=Content.HeaderButtonClickCommand}"/>
</i:Interaction.Behaviors>
<ig:ContextMenuService.Manager>
<!--If you use the Infragistics Commanding Framework, you should set the OpenMode property to None-->
<ig:ContextMenuManager ModifierKeys="None" OpenMode="RightClick">
<ig:ContextMenuManager.ContextMenu>
<ig:XamContextMenu HorizontalAlignment="Left" Name="xamContextMenu11" VerticalAlignment="Top">
<ig:XamMenuItem Header="Import" IsEnabled="{Binding Source={StaticResource DC1}, Path=Content.ImportMenuIsEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Source={StaticResource DC1}, Path=Content.ImportMenuCommand}"
CommandParameter="IMPORT"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ig:XamMenuItem>
<ig:XamMenuItem Header="Export" IsEnabled="{Binding Source={StaticResource DC1}, Path=Content.ExportMenuIsEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Source={StaticResource DC1}, Path=Content.ExportMenuCommand}"
CommandParameter="EXPORT"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ig:XamMenuItem>
<ig:XamMenuItem Header="Revert to Original" IsEnabled="{Binding Source={StaticResource DC1}, Path=Content.RevertMenuIsEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Source={StaticResource DC1}, Path=Content.RevertMenuCommand}"
CommandParameter="REVERT"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ig:XamMenuItem>
<ig:XamMenuItem Header="Graph" IsEnabled="{Binding Source={StaticResource DC1}, Path=Content.GraphMenuIsEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Source={StaticResource DC1}, Path=Content.GraphMenuCommand}"
CommandParameter="GRAPH"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ig:XamMenuItem>
</ig:XamContextMenu>
</ig:ContextMenuManager.ContextMenu>
</ig:ContextMenuManager>
</ig:ContextMenuService.Manager>
</ToggleButton>
<ListBox Grid.Row="1" Height="Auto" x:Name="listBox1" Width="Auto" HorizontalAlignment="Stretch"
ItemsSource="{Binding Path=Profile, Mode=TwoWay}" SelectionMode="Extended"
dp:ListBoxExtenders.AutoScrollToCurrentItem="True">
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Background" Value="{Binding Path=Status, Converter={StaticResource ProfileStatusIndicator}}"/>
</Style>
</ListBox.Style>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" Style="{StaticResource BucketProfileStyle}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Stretch">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<!--</ItemsControl>-->
</ListBox>
</toolkit:ListBoxDragDropTarget>
</toolkit:DockPanel>
</ScrollViewer>
So using a dragdropTarget, i was able to achieve the required result, leaving the complete solution above just for clarity.
<toolkit:ListBoxDragDropTarget AllowDrop="True" AllowedSourceEffects="Move" toolkit:DockPanel.Dock="Left" BorderThickness="0" Padding="0" VerticalAlignment="Top">
Solved using drag drop targets, updated solution posted above if somebody wants it.

Categories

Resources