In my Xamarin Forms application I would like to perform a validation on an Entry element when the user focus it out. Using Completed event only works when the user taps "enter" on the keyboard. I tried to use Unfocused but this event triggers while the user is typing on the Entry element and I really do not understand why.
How could I perform a piece of code only when an Entry element is unfocused?
I've 10 ViewCell elements like this one:
<ViewCell >
<StackLayout Orientation="Horizontal" Padding="13, 5" >
<StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" Spacing="1">
<Label Text="Matricola" VerticalOptions="Center" HorizontalOptions="StartAndExpand" ></Label>
<Entry x:Name="matricola" Text="{Binding Paziente.MatricolaPaziente, Mode=TwoWay}" HorizontalOptions="FillAndExpand" Completed="Entry_Completed" Unfocused="Entry_Completed" ></Entry>
<Label Text="{Binding RegistrationValidator.MatricolaError, Mode=OneWay}" HorizontalOptions="FillAndExpand" TextColor="IndianRed"></Label>
</StackLayout>
</StackLayout>
</ViewCell>
Code behind:
private async void Entry_Completed(object sender, EventArgs e){
// Some code here
}
Moreover the event triggers with unexpected random senders (other Entry elements, always with e.IsFocused == false)
The Entry focus issue inside ListView seems to occur (on second row of the ListView and onwards) on Android (8.1 and 9.0) (Xamarin.Forms 4.5.0.356).
See also "Entry focus issue inside ListView".
As a workaround, use CollectionView (without ViewCell in ItemTemplate).
Sample without Entry focus issue:
<CollectionView>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>First</x:String>
<x:String>Second</x:String>
</x:Array>
</CollectionView.ItemsSource>
<CollectionView.ItemTemplate>
<DataTemplate>
<Entry Text="collectionview" Focused="Entry_Unfocused" Unfocused="Entry_Unfocused" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Sample with Entry focus issue in ListView on Android (8.1 and 9.0):
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>First</x:String>
<x:String>Second</x:String>
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Entry Text="listview" Focused="Entry_Unfocused" Unfocused="Entry_Unfocused" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Codebehind for observing the focus events:
void Entry_Unfocused(object sender, FocusEventArgs e)
{
Debug.WriteLine($"Entry_Unfocused:{e.IsFocused}:");
}
void Entry_Focused(object sender, FocusEventArgs e)
{
Debug.WriteLine($"Entry_Focused:{e.IsFocused}:");
}
I tried with a sample forms like this
<ContentPage.Content>
<StackLayout Spacing="20" Padding="15">
<Label Text="Text" FontSize="Medium" />
<Entry Text="{Binding Item.Text}" d:Text="Item name" FontSize="Small" Unfocused="Entry_Unfocused" Completed="Entry_Completed" />
<Label Text="Description" FontSize="Medium" />
<Editor Text="{Binding Item.Description}" d:Text="Item description" FontSize="Small" Margin="0" />
</StackLayout>
</ContentPage.Content>
And in the code behind:
private void Entry_Unfocused(object sender, FocusEventArgs e)
{
var txt = ((Entry)sender).Text;
DisplayAlert("Info", $"Value of text after entry lost focus : {txt} ", "OK");
}
private void Entry_Completed(object sender, EventArgs e)
{
var txt = ((Entry)sender).Text;
DisplayAlert("Info", $"Value when Enter Key is tapped : {txt} ", "OK");
}
Everything works fine! While looking into your code again, it seems your are in listview. Maybe the problem might come from there.
I believe the Unfocused event gets triggered regardless of focus or unfocus, but the FocusEventArgs on the event should have a bool called IsFocused which should show whether or not the Entry is still focused. Have you tried checking that? It looks like you Unfocused Event Handler just uses a generic EventArgs when it could be using the more specific FocusEventArgs
Unfocused event is raised whenever the Entry loses focus. I make a simple code to test and verify.
Xaml:
<ListView ItemsSource="{Binding list}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Entry Text="{Binding Name}" Unfocused="Entry_Unfocused" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code:
public partial class EntryPage : ContentPage
{
public ObservableCollection<Person> list { get; set; }
public EntryPage()
{
InitializeComponent();
list = new ObservableCollection<Person>()
{
new Person (){ Name="A"},
new Person (){ Name="B"}
};
this.BindingContext = this;
}
private void Entry_Unfocused(object sender, FocusEventArgs e)
{
}
}
public class Person
{
public string Name { get; set; }
}
Related
I'm making a weather application and on one of the pages, users can save cities to quickly look up the weather for that city. I also want them to be able to delete a city in the list by pressing and holding and then dragging it to the delete button on the bottom of the screen.
The problem is that the label for the city name is the width of the entire screen and when you press and hold a city, you automatically grab the center of this label. Because of this, when you press the city name to much to the left of the label, the name disappears outside of the screen.
I can think of 2 possible solutions; make the screen have some kind of boundaries so nothing can disappear or make the label the width of the text within. But I can't find any of these solutions online. Does someone know how to do this or maybe has another solution?
This is the code for the xaml file.
<StackLayout>
<CollectionView x:Name="CitiesListView"
ItemsSource="{Binding Cities}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10" x:DataType="model:City">
<Label Text="{Binding name}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListCityTextStyle}"
FontSize="16" />
<StackLayout.GestureRecognizers>
<DragGestureRecognizer DragStartingCommand="{Binding Path=DragStartingCommand, Source={RelativeSource AncestorType={x:Type local:CitiesViewModel}}}" DragStartingCommandParameter="{Binding .}"/>
<TapGestureRecognizer
NumberOfTapsRequired="1"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:CitiesViewModel}}, Path=CityTapped}"
CommandParameter="{Binding .}">
</TapGestureRecognizer>
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<StackLayout HorizontalOptions="Center" VerticalOptions="FillAndExpand" Padding="5,10,5,10">
<StackLayout.GestureRecognizers>
<DropGestureRecognizer DropCommand="{Binding DropOverCommand}"/>
</StackLayout.GestureRecognizers>
<Image HeightRequest="40"
WidthRequest="40"
Source="trash_icon.png"
HorizontalOptions="EndAndExpand"/>
</StackLayout>
</StackLayout>
And this is the code for the drag and drop commands
public Command DragStartingCommand => new Command<City>((param) =>
{
var dur = TimeSpan.FromSeconds(0.1);
Vibration.Vibrate(dur);
_dragCity = param;
});
public Command DropOverCommand => new Command(() =>
{
if (Cities.Contains(_dragCity))
{
Cities.Remove(_dragCity);
removeCity(_dragCity);
}
});
public async void removeCity(City city)
{
await DataStore.DeleteCityAsync(city.id);
}
private City _dragCity;
Here is also a link to a video maybe better understand what I am talking about. Video
You could try to set the DragGestureRecognizer for the Label instead of StackLayout. A simple example for your reference. The text of Label would on the point which you pressed.
Xaml:
private async void OnDropGestureRecognizerDragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Copy;
}
private async void OnDropGestureRecognizerDrop(object sender, DropEventArgs e)
{
await DisplayAlert("Correct", "Congratulations!", "OK");
//await DisplayAlert("Incorrect", "Better luck next time.", "OK");
}
Code behind:
<StackLayout Margin="20">
<Label Text="Answer the following question by dragging your answer to the Entry." />
<Label Text="What's 2+2?" />
<Grid ColumnDefinitions="0.5*, 0.5*"
Margin="0,20,0,0">
<Label Text="3"
HorizontalOptions="Center">
<Label.GestureRecognizers>
<DragGestureRecognizer />
</Label.GestureRecognizers>
</Label>
<Label Grid.Column="1"
Text="4"
HorizontalOptions="Center">
<Label.GestureRecognizers>
<DragGestureRecognizer />
</Label.GestureRecognizers>
</Label>
</Grid>
<Entry Margin="0,20,0,0"
Placeholder="Drag your answer here">
<Entry.GestureRecognizers>
<DropGestureRecognizer DragOver="OnDropGestureRecognizerDragOver"
Drop="OnDropGestureRecognizerDrop" />
</Entry.GestureRecognizers>
</Entry>
</StackLayout>
I have two CollectionViews in my ContentPage inside a StackLayout, one above the other. Each binds to a separate ItemsSource. Above each one I have a Label. At this point each one take up 50% of the screen and scrolls separately.
I would like everything to scroll as though it were one long list.
So I surrounded everything with a ScrollView. But then, depending on where you put your finger, the scroll may scroll the entire page (which is what I want) or just the current CollectionView.
It seems like there is no way to cancel the scroll capability of the CollectionView. Is that true? and if not, How should I set up my ContentPage ?
In the below example both CollectionViews have the same model and binding but in reality they will be different.
Here is the xaml:
<RefreshView
x:DataType="local:AllRestaurantsViewModel"
Command="{Binding LoadItemsCommand}"
IsRefreshing="{Binding IsBusy, Mode=TwoWay}">
<ScrollView>
<StackLayout>
<Label
FontSize="Large"
HorizontalOptions="Center"
Text="Suggested Restaurants" />
<CollectionView
x:Name="ItemsListView"
ItemsSource="{Binding SuggestedRestsComments}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10" x:DataType="model:SuggestedRestsComment">
<Label
FontSize="16"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
Text="{Binding restaurantName}" />
<Label
FontSize="13"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
Text="{Binding CityName}" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemsViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}"
NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<Label
FontSize="Large"
HorizontalOptions="Center"
Text="Existing Restaurants" />
<CollectionView
x:Name="ItemsListView2"
ItemsSource="{Binding SuggestedRestsComments}"
SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Padding="10" x:DataType="model:SuggestedRestsComment">
<Label
FontSize="16"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemTextStyle}"
Text="{Binding restaurantName}" />
<Label
FontSize="13"
LineBreakMode="NoWrap"
Style="{DynamicResource ListItemDetailTextStyle}"
Text="{Binding CityName}" />
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type local:ItemsViewModel}}, Path=ItemTapped}"
CommandParameter="{Binding .}"
NumberOfTapsRequired="1" />
</StackLayout.GestureRecognizers>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ScrollView>
</RefreshView>
You could have a try with Custom CollectionViewRenderer to achieve that in each platform.
For example, send a mesage in Forms:
void OnButtonClicked(object sender, EventArgs e)
{
MessagingCenter.Send<object>(this, "StopScrollinng");
}
Then in iOS CustomCollectionViewRenderer class stop scrolling:
public class CustomCollectionViewRenderer: CollectionViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<GroupableItemsView> e)
{
base.OnElementChanged(e);
MessagingCenter.Subscribe<object>(this, "StopScrollinng", (sender) =>
{
// Do something whenever the "StopScrollinng" message is received
if (Control != null)
{
NSArray s = Control.ValueForKey(new NSString("_subviewCache")) as NSMutableArray;
UICollectionView c = s.GetItem<UICollectionView>(0);
c.SetContentOffset(c.ContentOffset, true);
}
});
}
}
And in Android CustomCollectionViewRenderer class stop scrolling:
public class CustomCollectionViewRenderer: CollectionViewRenderer
{
public CustomCollectionViewRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<ItemsView> elementChangedEvent)
{
base.OnElementChanged(elementChangedEvent);
MessagingCenter.Subscribe<object>(this, "StopScrollinng", (sender) =>
{
// Do something whenever the "StopScrollinng" message is received
this.DispatchTouchEvent(MotionEvent.Obtain(SystemClock.UptimeMillis(), SystemClock.UptimeMillis(), MotionEventActions.Cancel, 0, 0, 0));
});
}
}
How about this?
In your scrollview set InputTransparent="True" this allows the input to go through to the layer underneath.
<ScrollView InputTransparent="True">
Then leave some white space (background) on the right side of the collection views.
Now when someone swipes in the white space, the entire page scrolls. And when someone swipes inside the collection view, the collection view scrolls.
taken from https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/populate-data
the idea is to not use two separate collectionviews and merge them into one by choosing a datatemplate at runtime
xmlns:controls="clr-namespace:<your namespace>.Controls"
<ContentPage.Resources>
<DataTemplate x:Key="DataTemplate1">
...
</DataTemplate>
<DataTemplate x:Key="DataTemplate2">
...
</DataTemplate>
<controls:DataTemplateSelector1 x:Key="DataTemplateSelector1"
Template1="{StaticResource DataTemplate1}"
Template2="{StaticResource DataTemplate2}" />
</ContentPage.Resources>
namespace <your namespace>.Controls
{
public class DataTemplateSelector1: DataTemplateSelector
{
public DataTemplate Template1 { get; set; }
public DataTemplate Template2 { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
//here you return which template you want to use based on the properties of "item" . e.g you can do item is SomeClass ? Template1 : Template2
}
}
}
<ScrollView>
<CollectionView x:Name="collection" ItemTemplate="{StaticResource DataTemplateSelector1}"></CollectionView>
</ScrollView>
I'm having a hard time with XAML in Xamarin. Forms: The page is called and displayed without loading the data from the ListView (although the ListView is rendered because it changes the background color in its region).
Then, after I give a touch in the area of the ListView the data is presented i.e. initially the ListView shows nothing and after my touch on the screen it displays the data. However I have no event calling any refresh. I have already made sure of the code that the data is being received by it in a correct manner. Does anyone have any suggestions?
The following is the XAML code:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Coletas.Layouts.DetalheColeta">
<ContentPage.ToolbarItems>
<ToolbarItem Name="itemVisualizar" Order="Primary" Icon="pesquisar.png" Text="Visualizar" Priority="0" />
</ContentPage.ToolbarItems>
<ListView x:Name="Coleta" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="#FFCC80">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Coleta, StringFormat='Coleta {0:000000}'}" FontAttributes="Bold" FontSize="12"/>
<Label Text="{Binding Remetente}" FontAttributes="Bold" FontSize="12"/>
<Label Text="{Binding EnderecoRem}"/>
<Label Text="{Binding BairroRem}"/>
<Label Text="{Binding CidadeRem}"/>
<Label Text="{Binding ReferenciaRem}"/>
<Label Text="{Binding Destinatario}" FontAttributes="Bold" FontSize="12"/>
<Label Text="{Binding CidadeDes}"/>
<StackLayout Orientation="Horizontal" >
<Label Text="{Binding Peso, StringFormat='Peso: {0:0.00}'}"/>
<Label Text=" "/>
<Label Text="{Binding Quantidade, StringFormat='Volume: {0:0.00}'}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
The code that calls the DetalheColeta page is the below. This code is on another separate page:
private void GradeColetas_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as GridList;
if (item != null)
{
var id = item.Coleta;
Navigation.PushAsync(new DetalheColeta(id));
((ListView)sender).SelectedItem = null;
};
}
Any idea?
Discovered! The problem is in the constructor of the DetalheColeta page when using the Task. There is nothing wrong with the XAML and the previous page call. I executed the program in UWP and the message appeared: "The application called an interface that was marshalled for a different thread". I was testing in the Xamarin Live Player and did not give error. When correcting the call came to work.
Before:
public DetalheColeta (int collection)
{
InitializeComponent ()
Coleta_DetalheAsync (Collection)
}
Now:
public DetalheColeta (int collection)
{
InitializeComponent ()
Coleta_DetalheAsync (collection).Wait ();
}
Before:
Private async void Coleta_DetalheAsync (int collection)
{
Code
}
Now:
Private async Task Coleta_DetalheAsync (int collection)
{
Code
}
I have a base grid
<Grid Grid.Row="1" Grid.Column="1" x:Name="GridName">
<StackLayout Orientation="Vertical">
<art:GridOptionsView ItemsSource="{Binding Items}" >
<art:GridOptionsView.ItemTemplate>
<DataTemplate>
<uikit:DashboardItemTemplate />
</DataTemplate>
</art:GridOptionsView.ItemTemplate>
</art:GridOptionsView>
</StackLayout>
</Grid>
which uses the following DashboardItemTemplate
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
BackgroundColor="White">
<ContentView.Content>
<Grid Padding="0">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center" Orientation="Vertical" Spacing="10">
<Grid>
<Label Text="" Style="{StaticResource FontIcon}" HorizontalTextAlignment="Center" Opacity="1" FontSize="130" TextColor="{Binding BackgroundColor}" VerticalOptions="Center" HorizontalOptions="Center" IsVisible="{Binding Source={x:Reference Root}, Path=ShowiconColoredCircleBackground}" />
<Label Text="{Binding Icon}" Style="{StaticResource FontIcon}" Opacity="1" TextColor="White" VerticalOptions="Center" HorizontalOptions="Center" />
</Grid>
<Label Text="{Binding Name}" TextColor="{Binding Source={x:Reference Root}, Path=TextColor}" FontSize="14" HorizontalTextAlignment="Center">
</Label>
</StackLayout>
</Grid>
</ContentView.Content>
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnWidgetTapped" />
</ContentView.GestureRecognizers>
</ContentView>
How can i capture the "OnWidgetTapped" event on my base xaml class?
I do this usually with a custom bindable property ParentBindingContext in my template:
public class MyTemplate : ContentPage
{
public static BindableProperty ParentBindingContextProperty = BindableProperty.Create(nameof(ParentBindingContext),
typeof(object), typeof(BasePageTemplate));
public object ParentBindingContext
{
get { return GetValue(ParentBindingContextProperty); }
set { SetValue(ParentBindingContextProperty, value); }
}
}
And then in your page (which contains the template) just set the ParentBindingContext:
<DataTemplate>
<template:MyTemplate ParentBindingContext="{Binding BindingContext, Source={x:Reference Name=MyPageName}}" />
</DataTemplate>
With that you can access the full BindingContext of your page in your template. The following example of a command shows how the template can bind to a command MyCommand, which is in the BindingContext of the page:
Command="{Binding ParentBindingContext.MyCommand, Source={x:Reference Name=MyTemplatePageName}}"
But this presupposes that your page has a BindingContext behind (like a ViewModel). This ViewModel then contains the "global" commands for the whole page. These commands (or just methods) can then be accessed by the template, because they know about the BindingContext of the page.
I changed an answer from flow description to the code. The idea is to create ItemTemplate programatically and pass to its constructor the page with list (or grid). Define a function ItemTemplateTapped and call it from template.
EventOnGridPage
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonRendererDemo.EventOnGridPage">
<ListView x:Name="listView" >
</ListView>
</ContentPage>
EventOnGridPage code behind
public partial class EventOnGridPage : ContentPage
{
public EventOnGridPage()
{
InitializeComponent();
listView.ItemsSource = new List<Contact>
{
new Contact { Name = "Kirti",Status = "True"},
new Contact { Name = "Nilesh",Status = "False"}
};
listView.ItemTemplate = new DataTemplate(loadTemplate);
}
private object loadTemplate()
{
return new ViewCell() { View = new EventOnGridTemplate(this) };
}
public void ItemTemplateTapped(string name)
{
DisplayAlert("ItemTemplateTapped", name, "OK");
}
}
EventOnGridTemplate xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonRendererDemo.EventOnGridTemplate"
BackgroundColor="Green">
<Label Text="{Binding Name}" x:Name="myLabel"></Label>
</ContentView>
EventOnGridTemplate code behind
public partial class EventOnGridTemplate
{
EventOnGridPage parent;
public EventOnGridTemplate(EventOnGridPage parent)
{
this.parent = parent;
InitializeComponent();
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += TapGestureRecognizer_Tapped;
myLabel.GestureRecognizers.Add(tapGestureRecognizer);
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
parent.ItemTemplateTapped(myLabel.Text);
}
}
If you already defined the tap gesture binding in the XAML code, you don't need to add the TapGestureRecognizer, simply sign your method to an event listener method:
Your XAML:
<ContentView.GestureRecognizers>
<TapGestureRecognizer Tapped="OnWidgetTapped" />
</ContentView.GestureRecognizers>
On C# code behind:
public void OnWidgetTapped(object sender, EventArgs args)
{
// do stuff here
}
You just need to implement your OnWidgetTapped method:
void OnWidgetTapped(object sender, System.EventArgs e)
{
// Do stuff here
}
Another solution. If you implemented OnWidgetTapped as was suggested you can use sender.Parent.Parent... till you get to the object you want - grid or page. Cast it to for example EventOnGridPage and then call the function of that object.
I'm trying to create custom controls derived from the framework controls that have the added functionality of rendering themselves as a TextBlock. I'm doing this because the built-in IsEnabled or IsReadOnly properties don't meet my needs. However, I don't see any overridable methods in the control that would give me the functionality I need.
Am I headed down the right path? If not, is there a better way to do this?
Ok, this example is thrown together - keep that in mind. You'll notice that Im using some telerik controls... but you should be able to get the gist of what im doing. Also, in this example i threw together, im not using a DataTemplateSelector... just selecting the template in the code behind.
Rough sketch of xaml...
<UserControl x:Class="Admin.ManagePositions"
...
Title="MainWindow"
Width="525"
Height="350">
<UserControl.Resources>
<DataTemplate x:Key="ReadPositionTemplate">
<StackPanel>
<TextBlock Text="{Binding PositionCode}" Style="{StaticResource H5}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<telerik:RadButton x:Name="btnEdit" Content="Edit" Click="btnEdit_Click" Command="{Binding DataContext.EditPositionCommand, ElementName=ucManagePositions}" />
<telerik:RadButton x:Name="btnDelete" Content="Delete Position" Style="{StaticResource AutoSizeButton}" Click="btnDelete_Click" Command="{Binding DataContext.DeletePositionCommand, ElementName=ucManagePositions}" />
</StackPanel>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="EditPositionTemplate">
<StackPanel>
<sdk:Label Target="{Binding ElementName=txtPositionCode}" />
<TextBox x:Name="txtPositionCode" Text="{Binding PositionCode, Mode=TwoWay, ValidatesOnExceptions=True,NotifyOnValidationError=True}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<telerik:RadButton x:Name="btnSaveEdit" Content="Save" Click="btnSaveEdit_Click" Command="{Binding DataContext.SavePositionCommand, ElementName=ucManagePositions}" />
<telerik:RadButton x:Name="btnCancelEdit" Content="Cancel" Click="btnCancelEdit_Click" Command="{Binding DataContext.ResetHighlightPositionCommand, ElementName=ucManagePositions}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid>
<telerik:RadTransitionControl x:Name="selectedPositionContainer" Loaded="selectedPositionContainer_Loaded" Content="{Binding HighlightedPosition}">
<telerik:RadTransitionControl.Transition>
<telerik:SlideAndZoomTransition />
</telerik:RadTransitionControl.Transition>
</telerik:RadTransitionControl>
</Grid>
</UserControl>
And a rough outline of the code behind:
namespace Admin
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class ManagePositions : UserControl {
public MainWindow()
{
InitializeComponent();
}
private void btnEdit_Click(object sender, RoutedEventArgs e)
{
DataTemplate dt = ucManagePositions.Resources["EditPositionTemplate"] as DataTemplate;
selectedPositionContainer.ContentTemplate = dt;
}
private void btnCancelEdit_Click(object sender, RoutedEventArgs e)
{
DataTemplate dt = ucManagePositions.Resources["ReadPositionTemplate"] as DataTemplate;
selectedPositionContainer.ContentTemplate = dt;
}
private void selectedPositionContainer_Loaded(object sender, RoutedEventArgs e)
{
DataTemplate dt = ucManagePositions.Resources["ReadPositionTemplate"] as DataTemplate;
selectedPositionContainer.ContentTemplate = dt;
}
}
}
Hope that helps!