Focus to a specific editable datagrid cell in wpf DataGrid on RowSelection - mvvm

I have four columns in a datagrid and fourth column is templated and has textbox which is always editable.
What i am trying to achieve here is when a row selection changes the highlighted row's fourth cell which is editable and has textbox in it should get focus.
I am ok to get this done in codebehind or xaml.
Here is what i did:
<DataGrid Name="MyGrid" SelectionChanged="MyGrid_OnSelectionChanged" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Str1}" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Str2}" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Str3}" IsReadOnly="True"/>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Str4}" GotFocus="UIElement_OnGotFocus" >
<TextBox.Style >
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell,AncestorLevel=1},Path=IsSelected}">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
private void PopulateDummies()
{
int i = 0;
List<SomeDummy> dummies = new List<SomeDummy>();
while (i < 10)
{
dummies.Add(new SomeDummy
{
Str1 = string.Format("Str1:{0}", i),
Str2 = string.Format("Str2:{0}", i),
Str3 = string.Format("Str3:{0}", i),
Str4 = string.Format("Str4:{0}", i)
});
i++;
}
MyGrid.ItemsSource = dummies;
}
private void MyGrid_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void UIElement_OnGotFocus(object sender, RoutedEventArgs e)
{
var txtB = sender as TextBox;
txtB.Focus();
txtB.SelectAll();
}
Nothing seems to work. Not sure what is the reason. Can anyone help

The statement
txtB.Focus();
effectively replaces the DataGridCell by a TextEditory control. In order to do this, the view needs to be updated and therefore the UI-tread needs to run.
The SelectAll can not run until the editor is created, so run it as a separate Dispatcher-job and replace it with the following:
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
txtB.SelectAll();
}), DispatcherPriority.Render);
This will do the trick and you don't need the SelctionChanged-event handler for this purpose.

Related

Fixed space between rows in FlexLayout?

FlexLayout adjusts the spacing between the rows of content so the whole of its area is filled:
Can it be set to have no spacing between rows, or a fixed one? So that the rows would be packed to the top of the FlexLayout, and below there would be unused space? I have tried different settings (AlignItems, VerticalOptions, AlignContent) but couldn't achieve the desired result...
P.S.: the elements' size is fixed. These are added programmaticaly.
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp3.ActivitiesPage">
<Grid RowDefinitions="50,*,75" ColumnDefinitions="200, *">
<ScrollView Grid.RowSpan="2" x:Name="ActScroll">
<VerticalStackLayout x:Name="Activities" Padding="5" />
</ScrollView>
<Frame Padding="5" Grid.Column="1">
<Entry x:Name="ActText" BackgroundColor="Grey" />
</Frame>
<FlexLayout Grid.Row="1" Grid.Column="1" x:Name="Picker" Direction="Row" Wrap="Wrap" Padding="5" />
<HorizontalStackLayout Grid.ColumnSpan="2" Grid.Row="2" Padding="5" >
<Button x:Name="btnAdd" Text="Add" Clicked="btnAdd_Clicked" Margin="10"/>
<Button x:Name="btnSave" Text="Save" Margin="10" IsEnabled="False" Clicked="btnSave_Clicked"/>
<Button x:Name="btnDelete" Text="Delete" Margin="10" IsEnabled="False" Clicked="btnDelete_Clicked"/>
</HorizontalStackLayout>
</Grid>
</ContentPage>
Code behind (fragment):
public ActivitiesPage()
{
InitializeComponent();
//color picker
var ActColors = new Color[]
{
Colors.DimGray,
Colors.DarkGray,
Colors.Linen,
Colors.AntiqueWhite,
Colors.PeachPuff,
Colors.Tan,
Colors.BurlyWood,
Colors.SandyBrown,
Colors.Peru,
Colors.Chocolate,
Colors.Firebrick,
Colors.DarkRed,
Colors.Brown,
Colors.IndianRed,
Colors.LightCoral,
Colors.LightPink,
Colors.PaleVioletRed,
Colors.HotPink,
Colors.DeepPink,
Colors.MediumVioletRed,
Colors.DarkMagenta,
Colors.DarkOrchid,
Colors.Orchid,
Colors.MediumPurple,
Colors.BlueViolet,
Colors.DarkSlateBlue,
Colors.RoyalBlue,
Colors.DodgerBlue,
Colors.DeepSkyBlue,
Colors.LightSkyBlue,
Colors.PaleTurquoise,
Colors.Turquoise,
Colors.MediumTurquoise,
Colors.Aqua,
Colors.LightSeaGreen,
Colors.SeaGreen,
Colors.DarkGreen,
Colors.ForestGreen,
Colors.LimeGreen,
Colors.PaleGreen,
Colors.YellowGreen,
Colors.Olive,
Colors.DarkGoldenrod,
Colors.DarkOrange,
Colors.Gold,
Colors.Orange,
Colors.OrangeRed,
Colors.Crimson,
Colors.DarkSalmon,
Colors.Coral,
};
foreach (var col in ActColors)
{
btn.Margin = 2;
btn.MinimumWidthRequest = 50;
btn.MaximumWidthRequest = 50;
btn.MaximumHeightRequest = 50;
btn.MinimumHeightRequest= 50;
btn.FontSize = 12;
btn.CornerRadius = 2;
Picker.Add(btn);
}
}
(this is why, source code goes a long way, when you post question)
Your FlexLayout is solved by:
AlignContent="Start" AlignItems="Start" Direction="Row" Wrap="Wrap"
There is nothing else that is needed to have what you want.
The interesting part is the code that is around this FlexLayout. How will you make sure that it gets its desired Width and Height? Easy way is to set its Width and Height request.
(Good way to write interface, is to set faint background of containers, to watch its borders when you make changes.)
Edit: Tested it:
<FlexLayout x:Name="flex" AlignContent="Start" AlignItems="Start" Direction="Row" Wrap="Wrap" BackgroundColor="AliceBlue" HorizontalOptions="FillAndExpand" HeightRequest="500">
And populated it:
for (int i = 0; i < 100; i++)
{
Button b = new Button();
b.WidthRequest = 25;
b.HeightRequest = 25;
b.Text = i.ToString();
flex.Add(b);
}
Everything is exactly like in your picture.

.NET MAUI Picker binding update is not working

I used MonkeysViewModel for the Picker configured in XAML as below:
<Picker Title="Select a monkey" x:Name="MonkeysPicker"
ItemsSource="{Binding Monkeys}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding SelectedMonkey}"
/>
<Label x:Name="SelectedMonkey" Text="{Binding SelectedMonkey.Name}" />
<Image x:Name="SelectedMonkeyImage" Source="{Binding SelectedMonkey.ImageUrl}" />
The problem is that Label and Image shown only during first display. Then if I select different value from picker - they did not updated despite that SelectedMonkey value updated properly.
The solution I found is only to add SelectedIndexChanged function and assign Label and Image manually:
void PickerSelectedIndexChanged(object sender, EventArgs e)
{
var picker = (Picker)sender;
int selectedIndex = picker.SelectedIndex;
if (selectedIndex != -1)
{
SelectedMonkey.Text = (picker.BindingContext).SelectedMonkey.Name;
SelectedMonkeyImage.Source= (picker.BindingContext).SelectedMonkey.ImageUrl;
}
}
Why XAML Binding for Label and Image is not working ?

Content view binding not working

I have ContentView which need ViewModel binding
Test.xaml
<ContentView.Content>
<Frame x:Name="HelpBaseFrame" BackgroundColor="White" CornerRadius="16" HorizontalOptions="Fill" VerticalOptions="Center">
<StackLayout>
<ListView HasUnevenRows="True" x:Name="lstview" SeparatorColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell IsEnabled="False">
<ScrollView x:Name="ScrollView" Orientation="Vertical" Padding="0, 1, 0, 0" BackgroundColor="Transparent" HorizontalOptions="Center">
<StackLayout>
<Label x:Name="LabelHeader" FontAttributes="Bold" Font="HiraginoSans-W6, 16"
HorizontalOptions="Center" Margin="0,20,0,0">
<Label.Text>
<Binding Path="HeaderData"></Binding>
</Label.Text>
</Label>
<local:LineSpacingLabel x:Name="LabelHeaderDesceiption" LineSpacing="6"
Font="HiraginoSans-W3, 16" FontAttributes="None" Margin="0,20,0,0">
<Label.Text>
<Binding Path="DescriptionData"></Binding>
</Label.Text>
</local:LineSpacingLabel>
</StackLayout>
</ScrollView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Frame>
</ContentView.Content>
BindingClass
public void SetData(Dictionary<string, string> dictionary)
{
............
lstview.ItemsSource = HelpDataList; // HelpDataList is observable collection of HElp Data
}
Model class :
public class HelpData : BaseViewModel
{
private string Header = string.Empty;
private string Description = string.Empty;
public string HeaderData
{
get { return Header; }
set
{
Header = value;
OnPropertyChanged("HeaderData");
}
}
public string DescriptionData { get; set; }
}
This view model for above view.
This binding is not working.
Is anything wrong?
This view model for above view.
This binding is not working.
Is anything wrong?
This view model for above view.
This binding is not working.
Is anything wrong?
You have to set bindingContext on the target control by using x:Reference markup extension.
BindingContext="{x:Reference Name=ViewModelField}"
Or
BindingContext="{x:Reference ViewModelField}"
Label.Text should be binding with string not viewModel.
Text="{Binding Path=Value}"
Or
Text="{Binding Value}" ( “Path=” part of the markup extension can be omitted if the path is the first item in the Binding markup extension)
Refer to Bindings
Update
<Binding> is not a valid tag.
Modify the label :
<Label Text="{Binding Path = HeaderData}">

Display image in Silverlight4 Datagrid using Entity Framework

I have Employee Entity of northwind database and one of the field of this entity is "Photo" which is of type "Binary".
Now my question is how should i display the "Photo"fields in the Silverlight 4 datagrid so that i can view the employee photo?
What do i need todo in my WCF code or my ModelView Code?
My XAML code is given below:
<navigation:Page x:Class="NorthWind.SMS.UI.Views.EmployeeListing"
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"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="EmployeeListing Page" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="50" MaxHeight="50" MinHeight="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Height="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Name="grid1" VerticalAlignment="Top" Width="Auto" />
<TextBlock Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="tbHeader" Text="Employee Listing" VerticalAlignment="Top" FontSize="14" FontFamily="Verdana" TextAlignment="Center" />
<sdk:DataGrid Grid.Row="1" ItemsSource="{Binding Path=Employees}" AutoGenerateColumns="False" Height="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Name="dgEmployee" VerticalAlignment="Top" Width="Auto" AlternatingRowBackground="{x:Null}">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Name">
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding EmployeeName.TitleOfCourtesy}"></Run>
<Run Text="{Binding EmployeeName.FirstName}"></Run>
<Run Text="{Binding EmployeeName.LastName}"></Run></TextBlock>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
<sdk:DataGridTextColumn Binding="{Binding Path=Title}" Header="Title" />
<sdk:DataGridTextColumn Binding="{Binding Path=HireDate}" Header="HireDate" />
<sdk:DataGridTextColumn Binding="{Binding Path=BirthDate}" Header="DOB" />
<sdk:DataGridTextColumn Binding="{Binding Path=HomePhone}" Header="Phone" />
<sdk:DataGridTextColumn Binding="{Binding Path=City}" Header="City" />
<sdk:DataGridTextColumn Binding="{Binding Path=Region}" Header="Region" />
<sdk:DataGridTextColumn Binding="{Binding Path=Country}" Header="Country" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</navigation:Page>
My ModelView Code is given below;
private void RefreshEmployees()
{
this.serviceClient.GetEmployeesListingCompleted += (s, e) =>
{
this.Employees = e.Result;
};
this.serviceClient.GetEmployeesListingAsync();
}
My WCF code that is getting the data is show below;
[OperationContract]
public IEnumerable<Employee> GetEmployeesListing()
{
using (var context = new NorthwindEntities())
{
//context.ContextOptions.LazyLoadingEnabled = false;
var result = context.Employees.ToList();
result.ForEach(e => context.Detach(e));
return result;
}
}
I found the answer to my question here is what i did;
Step 1:
WCF code modified to convert the Binary "Photo" field to Jpeg format.
Code is shown below;
[OperationContract]
public IEnumerable<Employee> GetEmployeesListing()
{
List<Employee> empList = new List<Employee>();
using (var context = new NorthwindEntities())
{
//context.ContextOptions.LazyLoadingEnabled = false;
var result = context.Employees.ToList();
result.ForEach(e => context.Detach(e));
//return result;
foreach (Employee emp in result)
{
Employee e = new Employee();
e.EmployeeName.TitleOfCourtesy = emp.EmployeeName.TitleOfCourtesy;
e.EmployeeName.FirstName = emp.EmployeeName.FirstName;
e.EmployeeName.LastName = emp.EmployeeName.LastName;
e.Title = emp.Title;
e.HireDate = emp.HireDate;
e.BirthDate = emp.BirthDate;
e.City = emp.City;
e.Region = emp.Region;
e.Country = emp.Country;
if (emp.Photo != null)
{
byte[] blob = emp.Photo;
using (MemoryStream ms = new MemoryStream())
{
ms.Write(blob, 78, blob.Length - 78);
Bitmap bm = (Bitmap)Image.FromStream(ms);
using (MemoryStream msJpg = new MemoryStream())
{
bm.Save(msJpg, ImageFormat.Jpeg);
e.Photo = msJpg.GetBuffer();
}
}
}
empList.Add(e);
}
return empList;
}
}
Step 2:
Create a Image Converter class implementing the IValueConverter interface in your Silverlight project.
Code is shown below;
public class ByteToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
byte[] pic = value as byte[];
if (value != null)
{
MemoryStream ms = new MemoryStream((byte[])value, false);
BitmapImage bmi = new BitmapImage();
bmi.SetSource(ms);
return bmi;
}
else return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Step 4
In the XAML file where you have your Data grid add a refernce of ByteToImageConverter class like this;
xmlns:src="clr-namespace:NorthWind.SMS.UI.Converters"
Step 5
Add a Static resource details in your XAML file like this;
<UserControl.Resources>
<src:ByteToImageConverter x:Key="ConvertToImage">
</src:ByteToImageConverter>
</UserControl.Resources>
Step 6
Update your datagrid image template like this;
<sdk:DataGridTemplateColumn>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image x:Name="img1" Source ="{Binding Path=Photo, Converter={StaticResource ConvertToImage}}" Width="75" Height="75" Visibility="Visible"/>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
This solution is working just fine for me.

Collapse/Visible UserControls on ButtonClick with MVVM - no swap mechanism -

In my scenario I have a MainView + MainViewModel, UserControl1 + UserControl 2.
In the MainView I have 2 buttons labeled: Button_ShowUserControl1 + Button_ShowUserControl2.
At the lower part of the MainView I have a "ContentGrid" which takes/should_take... every UserControl.
My goal:
When Button_ShowUserControl1 is clicked UserControl1 is Visible and UserControl2 OR any other UserControl must be set to Collapsed. Same is valid for Button_ShowUserControl2.
My problem:
1.) As the UserControls shall be loaded at application start how can I put them all together in the one "ContentGrid"? Thats actually not possible... so how can I make one UserControl visible while the other is in the same place/"ContentGrid" just collapsed ?
2.) As 1.) seems not possible how can I instantiate all UserControls at start of the application and make them only Visible/Collapsed when respective Button is clicked?
3.) As a UserControl has a property Visibility = Visible/Hidden/Collapsed, how can I bind to a property in a ViewModel return such a value like Collapsed? I only could get a boolean value like Visibility = false/true ?
My testcode:
<Grid x:Name="LayoutRoot" Background="#FFBDF5BD" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="96*" />
<RowDefinition Height="289*" />
</Grid.RowDefinitions>
<Grid HorizontalAlignment="Stretch" Name="MenuGrid" VerticalAlignment="Stretch" Background="#FFCECEFF">
<StackPanel Name="stackPanel1" Background="#FFEDFF00" Orientation="Horizontal">
<Button Content="User Data 1" Height="35" Name="button1" Command="{Binding Path=ShowUserControl1Command}" Width="150" Margin="100,0,0,0" />
<Button Content="User Data 2" Height="35" Name="button2" Width="150" Margin="100,0,0,0" />
</StackPanel>
</Grid>
<Grid Grid.Row="1" HorizontalAlignment="Stretch" Name="ContentGrid" VerticalAlignment="Stretch" Background="#FFB15454" />
</Grid>
<UserControl x:Class="SwapUserControls.MVVM.UserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:SwapUserControls.MVVM.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Visibility="{Binding IsUserControl1Collapsed, Path=Value}">
<UserControl.Resources>
<vm:MainViewModel x:Key="MainViewModelID" />
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource MainViewModelID}" />
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="228*" />
<RowDefinition Height="72*" />
</Grid.RowDefinitions>
<Button Content="UserControl2" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="112,27,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
<DataGrid HorizontalAlignment="Stretch" Name="dataGrid1" VerticalAlignment="Stretch" Background="#FFC046F8" />
</Grid>
public class MainViewModel : ViewModelBase
{
RelayCommand _ShowUserControl1Command;
private bool _IsUserControl1Collapsed;
public RelayCommand ShowUserControl1Command
{
get
{
if (_ShowUserControl1Command == null)
{
_ShowUserControl1Command = new RelayCommand( () => ShowUserControl1() );
}
return _ShowUserControl1Command;
}
}
public void ShowUserControl1()
{
_IsUserControl1Collapsed = true;
}
public bool IsUserControl1Collapsed
{
get
{
return _IsUserControl1Collapsed;
}
}
}
Yes the code is wrong, therefore I ask here :)
You only have 2 things wrong with this code.
1) You can't set the visibility of a usercontrol directly... you have to set it on a container:
<Grid Visibility="Collapsed">
<myControls:MyUserControl />
</Grid>
2) Visibility is not a boolean value, it is an enum. As such, you will need to use a converter to convert from boolean to Visibility. Observe:
<Window ...>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>
<Grid Visibility="{Binding ShouldShowUsercontrol1, Converter={StaticResource BoolToVis}}">
<myControls:MyUserControl />
</Grid>
</Window>
That should be it. Hope this helps.
There are other things that you are leaving clues about that might affect the ability of this to work. For example, you don't show the biggest container element... are you wrapping everything in a StackPanel? If you are wrapping everything in a Grid, for example, the controls will overlay everything in layers.
Try these changes I suggest... it should get you closer.
Edit: Another idea using data templates
Another thing you could do is make sure you have a unique ViewModel for each of these views you want to show and hide:
public class MyFirstViewModel : ViewModel
{
}
public class MySecondViewModel : ViewModel
{
}
Then from your "parent" or "main" ViewModel, you show or hide the views you want by virtue of having them in a collection of ViewModels:
public MyMainViewModel : ViewModel
{
public ObservableCollection<ViewModel> ViewsToShow
{
...
}
public void ShowFirstViewModel()
{
ViewsToShow.Add(new MyFirstViewModel());
}
}
To wire everything up in your view, you would then datatemplate these types with their user controls (but this would not cause those views to be instantiated unless they were needed:
<Window ...>
<Window.Resources>
<DataTemplate DataType="{x:Type myViewModels:MyFirstViewModel}">
<myViews:MyFirstView />
</DataTemplate>
<DataTemplate DataType="{x:Type myViewModels:MySecondViewModel}">
<myViews:MySecondView />
</DataTemplate>
</Window.Resources>
<ItemsControl ItemsSource="{Binding ViewsToShow}" />
</Window>
And for any ViewModels you put in "ViewsToShow", the view will automatically see that and template in the appropriate view. Again, without instantiating it before it's needed.
This is probably a little cleaner than putting everything single thing in the View and setting visibility, but it would be dependent on you have a unique view model type for every view, which might not be the case.
The question of saving state comes up when using the DataTemplated approach. The solution here is to tread your ViewModel as the state of the control and design both your ViewModels and your Views accordingly. Here is an example that allows you to swap out your Views using DataTemplating, but switching back and forth saves state.
Assume you have the setup from the last section w/ 2 viewmodels that have datatemplates defined. Let's change up the MainViewModel a little:
public MyMainViewModel : ViewModel
{
public RelayCommand SwapViewsCommand
{
...
}
public ViewModel View
{
...
}
private ViewModel _hiddenView;
public MyMainViewModel()
{
View = new MyFirstViewModel();
_hiddenView = new MySecondViewModel();
SwapViewsCommand = new RelayCommand(SwapViewModels);
}
public void SwapViewModels()
{
var hidden = _hiddenView;
_hiddenView = View;
View = hidden;
}
}
And a few changes to the main view. I've omitted the DataTemplates for brevity.
<Window ...>
<!-- DataTemplates Here -->
<Button Command="{Binding SwapViewsCommand}">Swap!</Button>
<ContentControl Content="{Binding View}" />
</Window>
That's it. The secret here is I'm saving the reference to the original view model. This way, let's say there is a string property in a viewmodel and an associated textbox in the DataTemplated usercontrol with a two-way binding then the state will essentially be saved.