I have the following code in XAML:
<data:DataGridTemplateColumn>
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image x:Name="picture" Width="200" Height="130" Visibility="Visible"/>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
How would do I this in the code behind (C#), without using this XAML code?
EDIT:
Here is the solution I am using:
Creating a Silverlight DataTemplate in code
This lets me do exactly what I want.
For example, you have a simple DataGrid
<sdk:DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items}">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn CellTemplate="{StaticResource ImageCellTemplate}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
If you want to have several templates applied to a single DataGridRow, you can change visibility of internal parts inside the template:
<DataTemplate x:Key="ImageCellTemplate">
<Grid>
<StackPanel Orientation="Horizontal" Visibility="{Binding IsImageTemplate}">
<Image Width="20" Height="20"/>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Visibility="{Binding IsTextBoxTemplate}">
<TextBlock Text="{Binding Id}" Foreground="Red"/>
<TextBox Text="{Binding Title}"/>
</StackPanel>
</Grid>
</DataTemplate>
There is the part with Image and the part with TextBox that are bound to the properties of an item view model (IsImageTemplate and IsTextBoxTemplate respectively). They are mutually exclusive and panels will not cover each other.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
var items = new List<ItemViewModel>()
{
new ItemViewModel{Id = 1, Title="First", IsImage = true},
new ItemViewModel{Id = 2, Title="Second", IsImage = false},
new ItemViewModel{Id = 3, Title="Third", IsImage = false}
};
this.DataContext = new MainViewModel { Items = items };
}
}
public class MainViewModel
{
public List<ItemViewModel> Items { get; set; }
}
public class ItemViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsImage { get; set; }
public Visibility IsImageTemplate
{
get { return (IsImage == true) ? Visibility.Visible : Visibility.Collapsed; }
}
public Visibility IsTextBoxTemplate
{
get { return IsImage == false ? Visibility.Visible : Visibility.Collapsed; }
}
}
Related
So here I have a MVVM form. the Form contains a Datagrid which is connected to the Databank. I also have a ComboBox which I want to use as a filter option. The Filter option shoud filter by the "AnlV nr" so when the user selects "01" from the ComboBox the datagrid should refresh and show only that "AnlV nr" that have "01" Below I will share you the code and you can see that i've gotten as far as showing the "AnlV" values in the ComboBox but I now do not know how to do the rest and make the filter work. Below is my Viewmodel and the Xaml code.
If anyone can help me with this I would really apreciate it.
Xaml Code:
<Window x:Class="QBondsFrontend.Views.Input.AnlVTexteView"
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:local="clr-namespace:QBondsFrontend.Views.Input" xmlns:input="clr-namespace:QBondsFrontend.ViewModels.Input" d:DataContext="{d:DesignInstance Type=input:AnlVTexteViewModel}"
mc:Ignorable="d"
Title="AnlVTexteView"
Width="800"
MinHeight="400"
Height="490"
MinWidth="1010"
MaxWidth="1010"
UseLayoutRounding="True">
<Grid Background="#A8A8A8" >
<StackPanel VerticalAlignment="Top" Background="#A8A8A8" Orientation="Horizontal" Height="57">
<Label
Content="AnlV Nr.:" Height="35" FontSize="12"/>
<ComboBox Background="LightGray" Height="20" Width="70" ItemsSource="{Binding lstAnlVTexte}" SelectedItem="{Binding Search}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding AnlVPara}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Height="18" Width="68" Margin="5, 0"
Content="Filter löschen" FontSize="11" Style="{StaticResource STL_ButtonStandard}"
x:Name="filterlöschen"
Command="{Binding icdFilterDelete}"/>
</StackPanel>
<StackPanel Background="LightGray" VerticalAlignment="Top" Height="177" Margin="0,57,0,0">
<DataGrid x:Name="datagridXAML"
Height="177"
ItemsSource="{Binding lstAnlVTexte, Mode=TwoWay}"
Style="{StaticResource STL_DataGridReporting}"
CellStyle="{StaticResource STL_DataGridCellReporting}"
ColumnHeaderStyle="{StaticResource STL_DataGridColumnHeaderReporting}"
AlternatingRowBackground="#A8A8A8"
CanUserResizeColumns="False"
>
<DataGrid.Columns>
<DataGridTextColumn Header="AnlV-Nr"
Binding="{Binding AnlVPara}"
Width="60"/>
<DataGridTextColumn Header="gültig ab"
Binding="{Binding TextGueltigAb}"
Width="68"/>
<DataGridTextColumn Header="Text"
Binding="{Binding ParaText}"
Width="750"/>
<DataGridTextColumn Header="Info"
Binding="{Binding Info}"
Width="*"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
<StackPanel Background="#A8A8A8" HorizontalAlignment="Center" Margin="10,268,0,141" Width="1010" >
<Label Content="Bearbeitungsbereich" FontWeight="Bold" FontSize="12" Height="33" />
</StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal" Background="#A8A8A8" HorizontalAlignment="Center"
Width="1010" Margin="0,294,0,0" Height="31">
<Label Height="25" Width="60" Margin="20, 0, 0, 0" Content="AnlV-Nr.:" />
<ComboBox IsEditable="True" Background="gray" Height="22" Width="69" ItemsSource="{Binding AnlVPara}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding lstAnlVTexte}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<CheckBox Height="15" Margin="10, 0, 0, 0" />
<Label Height="26" Width="122" Content="Editierwarnungen" />
<StackPanel Height="48" Width="100"/>
</StackPanel>
<StackPanel Height="22" Orientation="Horizontal">
<Label Margin="20, 0, 0, 0" Content="gültig ab:" Height="27" />
<TextBox Background="LightGray" Height="20" Width="100" />
</StackPanel>
<StackPanel Height="50" Orientation="Horizontal">
<Label Content="Text:" Height="27" Width="38" Margin="42,0,0,10" />
<TextBox Background="LightGray" Width="500" Height="43" />
</StackPanel>
<StackPanel Orientation="Horizontal" >
<Label Content="Info:" Height="27" Width="38" Margin="42,0,0,0" />
<TextBox Background="LightGray" Width="500" Height="20" />
<Button x:Name="BTN_speichern" Width="80" Height="18" Margin="20,0,0,0" Content="Speichern"
Style="{StaticResource STL_ButtonStandard}" Command="{Binding icdSpeichern}"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
ViewModel:
using Newtonsoft.Json;
using QBondsData.DBModels;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Linq;
namespace QBondsFrontend.ViewModels.Input
{
public class AnlVTexteViewModel : BaseViewModel
{
#region data
private string _AnlVPara;
private DateTime _TextGueltigAb;
private string _ParaText;
private string _Info;
private List<AnlVhistText> _lstAnlVTexte;
private string _search;
#endregion
#region constructor
public AnlVTexteViewModel()
{
icdFilterDelete = new RelayCommand<object>(parameter => filterdelete(), parameter => true);
icdSpeichern = new RelayCommand<object>(parameter => speichern(), parameter => true);
GetData();
}
#endregion
#region members
public ICommand icdFilterDelete { get; set; }
public ICommand icdSpeichern { get; set; }
private string Search
{
get { return _search; }
set
{
_search = value;
OnPropertyChanged("Search");
}
}
public string AnlVPara
{
get
{
return _AnlVPara;
}
set
{
_AnlVPara = value;
OnPropertyChanged("AnlVPara");
}
}
public DateTime TextGueltigAb
{
get
{
return _TextGueltigAb;
}
set
{
_TextGueltigAb = value;
OnPropertyChanged("TextGueltigAb");
}
}
public string ParaText
{
get
{
return _ParaText;
}
set
{
_ParaText = value;
OnPropertyChanged("ParaText");
}
}
public string Info
{
get
{
return _Info;
}
set
{
_Info = value;
OnPropertyChanged("Info");
}
}
public List<AnlVhistText> lstAnlVTexte
{
get { return _lstAnlVTexte; }
set
{
_lstAnlVTexte = value;
OnPropertyChanged("lstAnlVTexte");
}
}
#endregion
#region methods
private void filterdelete()
{
}
private void speichern()
{
}
private async Task GetData()
{
HttpResponseMessage Response = await Globals.SendRequest("AnlVTexte/GetAnlVTexte"
, "GET");
if (Response.IsSuccessStatusCode)
{
lstAnlVTexte = JsonConvert.DeserializeObject<List<AnlVhistText>>
(await Response.Content.ReadAsStringAsync());
}
else
{
lstAnlVTexte = new List<AnlVhistText>();
Application.Current.Dispatcher.Invoke((Action)delegate
{
Globals.CloseReportByHash(this.GetHashCode()
, "Fehler! (HTTP Status " + Response.StatusCode + ")." +
"Kontaktieren Sie den Support.");
});
}
}
#endregion
}
}
When you change the type of lstAnlVTexte to ICollectionView you get two events CurrentChanged and CurrentChanging which you can handle in your viewmodel. From the ICollectionView you can get the CurrentItem.
Like this:
private List<AnlVhistText> _anlVTexte = new List<AnlVhistText>();
public AnlVTexteViewModel()
{
[...]
lstAnlVTexte = new CollectionView(_anlVTexte);
lstAnlVTexte.CurrentChanged += SelectionChanged; // raised after the current item has been changed.
lstAnlVTexte.CurrentChanging += SelectionChanging; // raise before changing the current item. Event handler can cancel this event.
}
private void SelectionChanged(object sender, EventArgs e)
{
var selectedItem = lstAnlVTexte.CurrentItem;
}
private void SelectionChanging(object sender, CurrentChangingEventArgs e)
{
}
private ICollectionView _lstAnlVTexte;
public ICollectionView lstAnlVTexte
{
get { return _lstAnlVTexte; }
set
{
_lstAnlVTexte = value;
OnPropertyChanged("lstAnlVTexte");
}
}
Here's a sample using the community toolkit mvvm and linq.
If you're not familiar, the toolkit does code generation.
This is a simple scenario to illustrate the approach.
Mainwindowviewmodel.
public partial class MainWindowViewModel : ObservableObject
{
[ObservableProperty]
private int selectedFilterInt = -1;
partial void OnSelectedFilterIntChanged(int newValue)
{
FilteredList = new ObservableCollection<MyItem>(FullList.Where(x=>x.Category == selectedFilterInt).ToList());
}
public List<int> FilterOptions { get; set; } = new List<int> {1,2,3};
private List<MyItem> FullList= new List<MyItem>
{
new MyItem{ Category = 1},
new MyItem{ Category = 1},
new MyItem { Category = 1 },
new MyItem { Category = 2 },
new MyItem { Category = 2 },
new MyItem { Category = 3 }
};
[ObservableProperty]
private ObservableCollection<MyItem> filteredList = new ObservableCollection<MyItem>();
public MainWindowViewModel()
{
FilteredList = new ObservableCollection<MyItem>(FullList);
}
}
There's a full list of all the items.
But a filtered list is going to be bound to the itemssource of my listbox ( equivalent to your datagrid ).
Due to the code generated, when selectedFilterInt changes, OnSelectedFilterIntChanged will be called. It's got a handler listening for property changed of SelectedFilterInt if you dug into the generated code.
That method uses a linq where to filter the full list into filtered list.
Setting that filtered list property raises property changed and the view re reads the new collection.
MainWindow. ( I did mention this is simplified )
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<ComboBox SelectedItem="{Binding SelectedFilterInt}"
ItemsSource="{Binding FilterOptions}"/>
<ListBox ItemsSource="{Binding FilteredList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Category}"/>
<TextBlock Text="{Binding Comment}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
</Window>
and MyItem
public partial class MyItem : ObservableObject
{
[ObservableProperty]
private int category = 0;
[ObservableProperty]
private string comment = "Some test string";
}
Which is a bit underwhelming visually but works:
In your code you need to get all the data into a collection.
Call that FulList.
You then need another collection which will be the filtered data.
Call this FilteredList.
Bind itemssource to FilteredList
Initially, you presumably want FilteredList to be = FullList
Then when the user selects something in the combobox you need to react to that.
You could bind selecteditem to a property and act in the setter or handle propertychanged like my code does.
However you do it, you get a new integer.
You then use that to filter FullList into a new collection which will replace the bound FilteredList.
You also need to somehow have one entry per AnlV nr whatever that is in your combobox.
AnlV nr isn't going to work as a property name since it's got a space but it is the equivalent to Category in my sample.
You will use that selected value in the linq.
Substitute the name of that property for Category. Substitute the type of whatever your collection is. Maybe that's AnlVhistText. I'm not sure.
Given these types
public class TestTypeBase
{
public string Name { get; set; }
}
public class TestTypeToggle : TestTypeBase
{
}
public class TestType : TestTypeBase
{
public bool Enabled { get; set; } = false;
}
this data context
public class vm
{
public ObservableCollection<TestTypeBase> TestTypes { get; } = new ObservableCollection<TestTypeBase> { new TestTypeToggle { Name = "Don't Test" }, new TestTypeToggle { Name = "Always Test" }, new TestType { Name = "qwert", Enabled = true }, new TestType { Name = "qwert", Enabled = true } };
}
(xaml)
<Page.DataContext>
<local:vm />
</Page.DataContext>
and this view
<ComboBox Width="120" ItemsSource="{Binding TestTypes}">
<ComboBox.Resources>
<DataTemplate x:Key="a" x:DataType="local:TestType">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<CheckBox IsChecked="{Binding Enabled}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="b" x:DataType="local:TestTypeToggle">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.Resources>
</ComboBox>
i was hoping that the ItemTemplate would be selected based on the item types but all i get are the type names as string.
This solution seems promising but i cannot figure how to give the type hint.
(I'm basically having the same problems as in this question but in a UWP context)
Is this possible or do i have to use a ItemTemplateSelector?
Yes, UWP is different from WPF. You have to use a ItemTemplateSelector in UWP.
Here are the official documents for your reference.
Page.xaml
<Page.Resources>
<DataTemplate x:Key="NormalItemTemplate" x:DataType="x:Int32">
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemChromeLowColor}">
<TextBlock Text="{x:Bind}" />
</Button>
</DataTemplate>
<DataTemplate x:Key="AccentItemTemplate" x:DataType="x:Int32">
<Button HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}">
<TextBlock Text="{x:Bind}" />
</Button>
</DataTemplate>
<local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
Normal="{StaticResource NormalItemTemplate}"
Accent="{StaticResource AccentItemTemplate}"/>
</Page.Resources>
<Grid>
<ListView x:Name = "TestListView"
ItemsSource = "{x:Bind NumbersList}"
ItemTemplateSelector = "{StaticResource MyDataTemplateSelector}">
</ListView>
</Grid>
Page.xaml.cs
public sealed partial class MainPage : Page
{
public ObservableCollection<int> NumbersList = new ObservableCollection<int>();
public MainPage()
{
this.InitializeComponent();
NumbersList.Add(1);
NumbersList.Add(2);
NumbersList.Add(3);
}
}
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Normal { get; set; }
public DataTemplate Accent { get; set; }
protected override DataTemplate SelectTemplateCore(object item)
{
if ((int)item % 2 == 0)
{
return Normal;
}
else
{
return Accent;
}
}
}
Edit
According to this document,
If your ItemsControl.ItemsPanel is an ItemsStackPanel or
ItemsWrapGrid, provide an override for the SelectTemplateCore(Object)
method. If the ItemsPanel is a different panel, such as
VirtualizingStackPanel or WrapGrid, provide an override for the
SelectTemplateCore(Object, DependencyObject) method.
So you need override the SelectTemplateCore(Object, DependencyObject) method in your DataTemplateSelector.
Page.xaml
<Page.Resources>
<DataTemplate x:Key="NormalItemTemplate" x:DataType="x:Int32">
<TextBox Text="{x:Bind}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemChromeLowColor}" />
</DataTemplate>
<DataTemplate x:Key="AccentItemTemplate" x:DataType="x:Int32">
<TextBox Text="{x:Bind}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{ThemeResource SystemAccentColor}" />
</DataTemplate>
<local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
Normal="{StaticResource NormalItemTemplate}"
Accent="{StaticResource AccentItemTemplate}"/>
</Page.Resources>
<Grid>
<ComboBox x:Name="Testcombox"
ItemsSource="{x:Bind NumbersList}"
ItemTemplateSelector = "{StaticResource MyDataTemplateSelector}">
</ComboBox>
</Grid>
Page.xaml.cs
public sealed partial class MainPage : Page
{
public ObservableCollection<int> NumbersList = new ObservableCollection<int>();
public MainPage()
{
this.InitializeComponent();
NumbersList.Add(1);
NumbersList.Add(2);
NumbersList.Add(3);
}
}
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate Normal { get; set; }
public DataTemplate Accent { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if ((int)item % 2 == 0)
{
return Normal;
}
else
{
return Accent;
}
}
}
How add near item in listview on left side small icon?
WPF Code:
<ListView Name="listView1" x:FieldModifier="public" HorizontalAlignment="Left" Height="501" Margin="10,10,0,0" VerticalAlignment="Top" Width="312">
<ListView.View>
<GridView>
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
Add item to listview
foreach (var item in found)
{
MainWindow.mainWindow.Dispatcher.Invoke(new Action(delegate ()
{
listView1.Items.Add(item);
}));
}
You just need to amend the DataTemplate as shown below.
POCO List View Item (Data Model):
public class MyListItem
{
public string Icon { get; set; }
public string Text { get; set; }
}
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var listItemObj = myListView.Items.Add(new MyListItem {Icon = "Default Icon", Text = "Default Text"});
}
}
XAML:
<ListView Name="myListView">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Icon}"/>
<TextBlock Text="{Binding Path=Text}" Padding="5 0 0 0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Result:
I am trying to navigate in between pages using listitems but its not working. My home page is MainPage.xaml and I want to navigate to "xyz" when I click on the Aba image in listview
Here is my code:
namespace abc
{
public sealed partial class MainPage : Page
{
ObservableCollection<Class1> list1 = new ObservableCollection<Class1>();
public MainPage()
{
this.InitializeComponent();
Filldata();
}
void Filldata()
{
list1.Add(new Class1 { name = "Aba", image = "ms-appx:///images/aba.png" });
list1.Add(new Class1 { name = "Al", image = "ms-appx:///images/al.png" });
}
private void itemclicked(object sender, ItemClickEventArgs e)
{
var nme = (Class1)e.ClickedItem;
switch (nme.name)
{
case "Aba":
Frame.Navigate(typeof(xyz),null);
break;
}
}
}
}
MainPage.xaml
<ListView x:Name="list" ItemClick="itemclicked">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="100" Width="100" Source="{Binding image}"></Image>
<TextBlock Text="{Binding name}" HorizontalAlignment="Center"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Class1.cs
class Class1
{
public String name { get; set; }
public String image { get; set; }
}
You have an issue with your ListView control and the main reason is that you don't have this property in your ListView in XAML:
IsItemClickEnabled="True"
So in order to solve your problem add this property IsItemClickEnabled="True" at ListView in XAML page like this:
<ListView x:Name="list"
ItemClick="itemclicked"
IsItemClickEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="100"
Width="100"
Source="{Binding image}"></Image>
<TextBlock Text="{Binding name}"
HorizontalAlignment="Center"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Your code is fine at navigation methods and other things but you need to "enable" items to be clicked, so add that property in order to can use them with click events.
I'm using Flipview and a DataTemplateSelector to determine at runtime which DataTemplate to apply to show items in my control.
I have two DataTemplate's, one is static and the second can be used by a undetermined number of items.
The problem is that the button does nothing. I've used a breakpoint in SaveCommand but when I click the button, it doesn't break.
XAML
<Page.Resources>
<DataTemplate x:Key="FirstDataTemplate">
<Grid>
<TextBlock Text="{Binding Content}" Margin="10,0,18,18"></TextBlock>
</Grid>
</DataTemplate>
<DataTemplate x:Key="SecondDataTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding Url}"></TextBox>
<Button Grid.Column="1" Name="SendButton"
Style="{StaticResource ImageButtonStyle}"
Command="{Binding Path=SaveCommand}"
HorizontalAlignment="Center">
<Grid>
<Image Source="ms-appx:///Skins/Images/buton.png" Stretch="None" />
<TextBlock Text="CLICK ME" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White"/>
</Grid>
</Button>
</Grid>
</DataTemplate>
<local:MyDataTemplateSelector x:Key="MyDataTemplateSelector"
FirstTextTemplate="{StaticResource FirstDataTemplate}"
SecondTextTemplate="{StaticResource SecondDataTemplate}">
</local:MyDataTemplateSelector>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<FlipView x:Name="itemGridView" ItemTemplateSelector="{StaticResource MyDataTemplateSelector}"
Margin="265,220,284,162">
</FlipView>
</Grid>
Code-Behind
public sealed partial class FlipViewDemo : Page
{
public FlipViewDemo()
{
this.InitializeComponent();
var items = new List<BaseClass>();
items.Add(new FirstItem
{
Content="This is a test - Content"
});
for (int i = 0; i < 18; i++)
{
items.Add(new SecondItem
{
Url = "http://www.google.com/ " + i.ToString()
});
}
itemGridView.ItemsSource = items;
}
}
public class BaseClass
{
}
public class FirstItem : BaseClass
{
public string Content { get; set; }
}
public class SecondItem : BaseClass
{
public string Url { get; set; }
}
public class MyDataTemplateSelector : DataTemplateSelector
{
public DataTemplate FirstTextTemplate { get; set; }
public DataTemplate SecondTextTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item is FirstItem)
return FirstTextTemplate;
if (item is SecondItem)
return SecondTextTemplate;
return base.SelectTemplateCore(item, container);
}
}
ViewModel
public class FisaObsViewModel : ViewModelBase
{
private RelayCommand saveCommand;
public FisaObsViewModel()
{
}
public RelayCommand SaveCommand
{
get
{
return saveCommand ?? (saveCommand = new RelayCommand(
async () =>
{
try
{
MessageDialog dlg = new MessageDialog("Message");
await dlg.ShowAsync();
}
catch (Exception)
{
throw;
}
}));
}
}
}
Some of the links that I've checked:
http://www.mutzl.com/tag/mvvm-light/
http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute
http://social.technet.microsoft.com/wiki/contents/articles/18199.event-handling-in-an-mvvm-wpf-application.aspx
The problem is that the DataTemplate is referencing your Model, not your ViewModel. So your command binding is trying to find the command on the Model.
You need to change your binding source to whatever element has it's DataContext set to the ViewModel.
{Binding DataContext.SaveCommand, RelativeSource={RelativeSource AncestorType=Page}}
Or
Give your Page a Name, and use the following binding:
{Binding DataContext.SaveCommand, ElementName=myPageName}