Są to wszystkie wielkie sugestii, ale jeśli byłbyś, zrobiłbym to w twoim modelu widzenia. W modelu widoku można utworzyć polecenie przekazywania, które następnie można powiązać z zdarzeniem kliknięcia w szablonie elementu. Aby określić, czy ten sam element został wybrany, możesz zapisać odniesienie do wybranego elementu w swoim modelu widoku. Lubię używać MVVM Light do obsługi wiązania. To sprawia, że twój projekt jest znacznie łatwiejszy do modyfikowania w przyszłości i umożliwia ustawienie wiązania w Blend.
Kiedy wszystko jest powiedziane i zrobione, twój XAML będzie wyglądać jak sugerował Sergey. Unikałbym używania kodu w twoim widoku. W tej odpowiedzi zamierzam unikać pisania kodu, ponieważ jest tam mnóstwo przykładów.
Oto jeden: How to use RelayCommand with the MVVM Light framework
Jeśli wymagają przykład, prosimy o komentarz, a dodam jeden.
~ Cheers
Powiedziałem, że nie zamierza zrobić przykład, ale jestem. Proszę bardzo.
1) Dodaj do swojego projektu tylko MVVM Light Libraries.
2) Utwórz klasę dla widoku. Ogólnie rzecz biorąc, masz model widoku dla każdego widoku (widok: MainWindow.xaml & & viewModel: MainWindowViewModel.cs)
3) Oto kod na bardzo, bardzo, bardzo podstawowy model Widok:
Wszystko wliczone nazw (jeśli pojawi się tutaj, jestem zakładając, że już dodane odniesienie do nich MVVM światła. jest w Nuget)
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
teraz dodaj podstawową klasę publiczną:
/// <summary>
/// Very basic model for example
/// </summary>
public class BasicModel
{
public string Id { get; set; }
public string Text { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="text"></param>
public BasicModel(string text)
{
this.Id = Guid.NewGuid().ToString();
this.Text = text;
}
}
teraz utworzyć ViewModel:
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
ModelsCollection = new ObservableCollection<BasicModel>(new List<BasicModel>() {
new BasicModel("Model one")
, new BasicModel("Model two")
, new BasicModel("Model three")
});
}
private BasicModel _selectedBasicModel;
/// <summary>
/// Stores the selected mode.
/// </summary>
/// <remarks>This is just an example, may be different.</remarks>
public BasicModel SelectedBasicModel
{
get { return _selectedBasicModel; }
set { Set(() => SelectedBasicModel, ref _selectedBasicModel, value); }
}
private ObservableCollection<BasicModel> _modelsCollection;
/// <summary>
/// List to bind to
/// </summary>
public ObservableCollection<BasicModel> ModelsCollection
{
get { return _modelsCollection; }
set { Set(() => ModelsCollection, ref _modelsCollection, value); }
}
}
W swoim widokumodułu dodaj ponowny odnośnik. Zauważ, że zrobiłem to asynchronicznie i kazałem mu przekazać parametr.
private RelayCommand<string> _selectItemRelayCommand;
/// <summary>
/// Relay command associated with the selection of an item in the observablecollection
/// </summary>
public RelayCommand<string> SelectItemRelayCommand
{
get
{
if (_selectItemRelayCommand == null)
{
_selectItemRelayCommand = new RelayCommand<string>(async (id) =>
{
await selectItem(id);
});
}
return _selectItemRelayCommand;
}
set { _selectItemRelayCommand = value; }
}
/// <summary>
/// I went with async in case you sub is a long task, and you don't want to lock you UI
/// </summary>
/// <returns></returns>
private async Task<int> selectItem(string id)
{
this.SelectedBasicModel = ModelsCollection.FirstOrDefault(x => x.Id == id);
Console.WriteLine(String.Concat("You just clicked:", SelectedBasicModel.Text));
//Do async work
return await Task.FromResult(1);
}
W kodzie tyłu dla przeglądać, tworzyć właściwość Ci ViewModel i ustawić datacontext dla swojego celu viewmodel (proszę pamiętać, że istnieją inne sposoby, aby to zrobić, ale staram się robić to prosty przykład.)
public partial class MainWindow : Window
{
public MainWindowViewModel MyViewModel { get; set; }
public MainWindow()
{
InitializeComponent();
MyViewModel = new MainWindowViewModel();
this.DataContext = MyViewModel;
}
}
W swojej XAML, trzeba dodać kilka nazw w górnej części kodu
<Window x:Class="Basic_Binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:Custom="clr-namespace:GalaSoft.MvvmLight;assembly=GalaSoft.MvvmLight"
Title="MainWindow" Height="350" Width="525">
dodałem "i" i "Custom".
Oto ListView:
<ListView
Grid.Row="0"
Grid.Column="0"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding ModelsCollection}"
ItemTemplate="{DynamicResource BasicModelDataTemplate}">
</ListView>
Oto ItemTemplate dla ListView:
<DataTemplate x:Key="BasicModelDataTemplate">
<Grid>
<TextBlock Text="{Binding Text}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction
Command="{Binding DataContext.SelectItemRelayCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding Id}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</Grid>
</DataTemplate>
Uruchom aplikację i sprawdź okno wyjściowe. Możesz użyć konwertera do obsługi stylizacji wybranego elementu.
To może wydawać się bardzo skomplikowane, ale znacznie ułatwia życie w czasie, gdy trzeba oddzielić widok od ViewModel (np. Stworzyć ViewModel dla wielu platform.) Dodatkowo ułatwia pracę w Blend 10x. Kiedy już stworzysz swój ViewModel, możesz przekazać go projektantowi, który może sprawić, że będzie wyglądać bardzo artystycznie :). MVVM Light dodaje trochę funkcjonalności, aby Blend rozpoznawał twój ViewModel. W większości można zrobić prawie wszystko, co chcesz w ViewModel, aby wpłynąć na widok.
Jeśli ktokolwiek to przeczyta, mam nadzieję, że ci się to przyda. Jeśli masz pytania, daj mi znać. W tym przykładzie użyłem MVVM Light, ale można to zrobić bez MVVM Light.
~ Cheers
Właściwie można ustawić obsługi bezpośrednio na 'ListView', nie istnieje potrzeba EventSetter. –