我有一個由字串和陣列組成的物件。根據選定的字串值,字串填充 a ComboBox,陣列填充 a 。ListView的每一行ListView由 aTextBlock和 a組成CheckBox。
在提交時,我希望能夠驗證已選擇哪些專案進行進一步處理,但使用 MVVM 方法時會出現斷開連接。我目前DataContext將提交Button系結到 ,ListView但在提交時只回傳第一個值(我需要將選定的值保存到我假設的串列中,但我不確定在哪里)。我在模型中添加了一個IsSelected屬性,我認為這是第一步,但在那之后我一直在抓住稻草。
模型
namespace DataBinding_WPF.Model
{
public class ExampleModel { }
public class Example : INotifyPropertyChanged
{
private string _name;
private string[] _ids;
private bool _isSelected;
public bool IsSelected
{
get => _isSelected;
set
{
if (_isSelected != value)
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
}
public string Name
{
get => _name;
set
{
if (_name != value)
{
_name = value;
RaisePropertyChanged("Name");
}
}
}
public string[] IDs
{
get => _ids;
set
{
if (_ids != value)
{
_ids = value;
RaisePropertyChanged("IDs");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(property));
}
}
}
}
視圖模型
namespace DataBinding_WPF.ViewModel
{
public class ExampleViewModel : INotifyPropertyChanged
{
public ObservableCollection<Example> Examples
{
get;
set;
}
// SelectedItem in the ComboBox
// SelectedItem.Ids will be ItemsSource for the ListBox
private Example _selectedItem;
public Example SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
RaisePropertyChanged(nameof(SelectedItem));
}
}
// SelectedId in ListView
private string _selectedId;
public string SelectedId
{
get => _selectedId;
set
{
_selectedId = value;
RaisePropertyChanged(nameof(SelectedId));
}
}
private string _selectedCheckBox;
public string IsSelected
{
get => _selectedCheckBox;
set
{
_selectedCheckBox = value;
RaisePropertyChanged(nameof(IsSelected));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(property));
}
}
public void LoadExample()
{
ObservableCollection<Example> examples = new ObservableCollection<Example>();
examples.Add(new Example { Name = "Mark", IDs = new string[] { "123", "456" }, IsSelected = false });
examples.Add(new Example { Name = "Sally", IDs = new string[] { "789", "101112" }, IsSelected = false });
Examples = examples;
}
/* BELOW IS A SNIPPET I ADDED FROM AN EXAMPLE I FOUND ONLINE BUT NOT SURE IF IT'S NEEDED */
private ObservableCollection<Example> _bindCheckBox;
public ObservableCollection<Example> BindingCheckBox
{
get => _bindCheckBox;
set
{
_bindCheckBox = value;
RaisePropertyChanged("BindingCheckBox");
}
}
}
}
看法
<UserControl x:Class = "DataBinding_WPF.Views.StudentView"
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:local = "clr-namespace:DataBinding_WPF"
mc:Ignorable = "d"
d:DesignHeight = "300" d:DesignWidth = "300">
<Grid>
<StackPanel HorizontalAlignment = "Left" >
<ComboBox HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="120"
ItemsSource="{Binding Path=Examples}"
SelectedItem="{Binding SelectedItem}"
DisplayMemberPath="Name"/>
<ListView x:Name="myListView"
ItemsSource="{Binding SelectedItem.IDs}"
DataContext="{Binding DataContext, ElementName=submit_btn}"
SelectedItem="{Binding SelectedId}"
Height="200" Margin="10,50,0,0"
Width="Auto"
VerticalAlignment="Top"
Background="AliceBlue">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<CheckBox
Name="myCheckBox"
IsChecked="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType=ListViewItem}}"
Margin="5, 0"/>
<TextBlock Text="{Binding}" FontWeight="Bold" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button HorizontalAlignment="Left" Height="20" Width="100"
Click="Submit" x:Name="submit_btn">Submit</Button>
</StackPanel>
</Grid>
</UserControl>
查看.cs
namespace DataBinding_WPF.Views
{
/// <summary>
/// Interaction logic for StudentView.xaml
/// </summary>
public partial class StudentView : UserControl
{
public StudentView()
{
InitializeComponent();
}
private void Submit(object sender, EventArgs e)
{
var selectedItems = ((Button)sender).DataContext;
// process each selected item
// foreach (var selected in ....) { }
}
}
}
uj5u.com熱心網友回復:
該ListView控制元件已將選定專案集合公開為屬性SelectedItems。
private void Submit(object sender, RoutedEventArgs e)
{
var selectedIds = myListView.SelectedItems.Cast<string>().ToList();
// ...do something with the items.
}
但是,我懷疑您是否想在代碼隱藏中執行此操作,而是在視圖模型中執行此操作。為此,WPF 提供了命令的概念。
- MVVM - 命令、RelayCommands 和 EventToCommand
您需要的是中繼命令或委托命令(名稱因框架而異)。它封裝了一個應該執行的方法,例如按鈕單擊和一個方法來確定該命令是否可以作為可以系結在視圖中的物件來執行。不幸的是,WPF 沒有提供開箱即用的實作,因此您要么必須復制此處的實作,要么使用已經提供的 MVVM 框架,例如Microsoft MVVM Tookit。
您將在您Submit的型別中公開一個型別的屬性,并在建構式中使用該委托給要執行的方法的實體對其進行初始化。ICommandExampleViewModelRelayCommand<T>
public class ExampleViewModel : INotifyPropertyChanged
{
public ExampleViewModel()
{
Submit = new RelayCommand<IList>(ExecuteSubmit);
}
public RelayCommand<IList> Submit { get; }
// ...other code.
private void ExecuteSubmit(IList selectedItems)
{
// ...do something with the items.
var selectedIds = selectedItems.Cast<string>().ToList();
return;
}
}
在您看來,您將洗掉Click事件處理程式并將Submit屬性系結Command到Button. 您還可以將屬性系結SelectedItems到ListView屬性CommandParameter,以便在執行時將所選專案傳遞給命令。
<Button HorizontalAlignment="Left"
Height="20"
Width="100"
x:Name="submit_btn"
Command="{Binding Submit}"
CommandParameter="{Binding SelectedItems, ElementName=myListView}">Submit</Button>
此外,關于您的 XAML 的一些評論。
XAML 中的控制元件名稱應為 Pascal-Case,以大寫字母開頭。
您應該完全洗掉
DataContext系結,因為它會自動接收與無論如何ListView相同的資料背景關系。ButtonDataContext="{Binding DataContext, ElementName=submit_btn}"通過對分層資料使用Master/Detail 模式,您可以避免在 中公開和系結
SelectedItem屬性。ExampleViewModel<Grid> <StackPanel HorizontalAlignment = "Left" > <ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" ItemsSource="{Binding Path=Examples}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/> <ListView ItemsSource="{Binding Examples/IDs}" SelectedItem="{Binding SelectedId}" Height="200" Margin="10,50,0,0" Width="Auto" VerticalAlignment="Top" Background="AliceBlue"> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" > <CheckBox Name="myCheckBox" IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}" Margin="5, 0"/> <TextBlock Text="{Binding}" FontWeight="Bold" /> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView> <Button HorizontalAlignment="Left" Height="20" Width="100" Command="{Binding Submit}" CommandParameter="{Binding SelectedItems, ElementName=myListView}">Submit</Button> </StackPanel> </Grid>
uj5u.com熱心網友回復:
如果視圖的資料背景關系系結到視圖,則從 ListView 中洗掉 DataContext。
您可以洗掉專案模板,而是使用 GridView,例如:
<ListView.View>
<GridView >
<GridViewColumn Header="Selected" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
由于 ItemSource 是一個 Observable 集合,因此有幾個選項可以監視復選框中的更改:
- 將事件處理程式添加到集合的專案更改事件,然后您可以將名稱或集合索引添加到本地集合。例如示例[e.CollectionIndex].Name
- 或者迭代可觀察集合并選擇那些 Selected = "true" 的示例
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/506330.html
下一篇:Xaml通過兩列制作元素
