如何获取模板组合框的值
How to get the value of a template combo box
我得到了一个模板组合框
<ComboBox x:Name="TryCombo" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="75"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Id}" Margin="4,0" Visibility="Collapsed" Grid.Column="0"/>
<TextBlock Text="{Binding Path=Name}" Margin="4,0" Grid.Column="1"/>
<Button x:Name="AddButton" Content="Add" Grid.Column="2"/>
</Grid>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
然后是 ItemsSource:
public void BindComboboxes()
{
itemMgr.Parameters = RetrieveFilter("");
itemMgr.EntityList = itemMgr.RetrieveMany(itemMgr.Parameters);
TryCombo.ItemsSource = itemMgr.EntityList; //collection;
}
组合框将载入:
我的问题是获取我用 AddButton 单击的选定项目,我想获取绑定到 Path=Id 的文本块的值,但是如何?
我应该为每个 TextBlocks 添加 x:Name 吗?
将您的 Button 绑定到 ViewModel 中的 ICommand-属性 并将所选项目作为 CommandParameter
传递
我为您制作了一个小型演示应用程序:
MainWindow.xaml 看起来像:
<Window x:Class="ComboBoxDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Content="Add Item to ComboBox" Margin="5" Command="{Binding AddItemCommand}"/>
<ComboBox Grid.Row="1" x:Name="TryCombo" ItemsSource="{Binding Parameters, UpdateSourceTrigger=PropertyChanged}" Margin="5">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Id}" Margin="4,2" VerticalAlignment="Center" Grid.Column="0"/>
<TextBlock Text="{Binding Path=Name}" Margin="4,2" Grid.Column="1" VerticalAlignment="Center"/>
<Button x:Name="AddButton" Content="Add" Grid.Column="2" VerticalAlignment="Center" Margin="4,2"
Command="{Binding DataContext.ComboBoxItemAddCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
CommandParameter="{Binding}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</Window>
重要的是 Window 声明中的部分:DataContext="{Binding RelativeSource={RelativeSource Self}}"
通过这个你告诉 Window 它的 DataContext 在代码隐藏文件中。您还可以使用另一个文件作为您的 DataContext。比你必须写:
<Window.DataContext>
<loc:MyClassName/>
</Window.DataContext>
这仅在您将 xmlns:loc="clr-namespace:YOURPROJECTNAMESPACE"
添加到 Window 声明时有效。对于我的演示,YOURPROJECTNAMESPACE 将是 ComboBoxDemo。
我还为参数创建了一个 class,它非常简单,看起来像:
public class Parameter
{
public string Id { get; set; }
public string Name { get; set; }
}
Window 的代码隐藏(记住:这是 MainWindow.xaml 的 DataContext)看起来像:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace ComboBoxDemo
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ICommand addItemCommand;
private ICommand comboBoxItemAddCommand;
private ObservableCollection<Parameter> parameters;
public MainWindow()
{
InitializeComponent();
Parameters = new ObservableCollection<Parameter>();
AddItemCommand = new RelayCommand(AddItem);
ComboBoxItemAddCommand = new RelayCommand(ComboBoxItemAdd);
}
private void ComboBoxItemAdd(object parameter)
{
Parameter para = parameter as Parameter;
if (para != null)
{
// Now you can use your Parameter
}
}
public ObservableCollection<Parameter> Parameters
{
get { return parameters; }
set
{
parameters = value;
OnPropertyChanged();
}
}
public ICommand AddItemCommand
{
get { return addItemCommand; }
set
{
addItemCommand = value;
OnPropertyChanged();
}
}
public ICommand ComboBoxItemAddCommand
{
get { return comboBoxItemAddCommand; }
set
{
comboBoxItemAddCommand = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void AddItem(object parameter)
{
Parameters.Add(new Parameter
{
Id = Guid.NewGuid().ToString(),
Name = "Any Name"
});
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我还创建了一个非常有用的 Helper-Class 如果您使用命令绑定,您可能总是需要它。这是classRelayCommand
。这个 class 有一个构造函数,它需要一个 Action<object>
类型的对象。此操作稍后包含单击按钮时将执行的操作。第二个可选参数我现在不解释。 RelayCommand 看起来像:
using System;
using System.Windows.Input;
namespace ComboBoxDemo
{
public class RelayCommand : ICommand
{
private readonly Action<object> execute;
private readonly Predicate<object> canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null )
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (canExecute == null)
return true;
return canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
所以。现在我将向您解释该过程:因此,我使用以下缩写
- V = MainWindow.xaml
- VM = MainWindow.xaml.cs
V 中的 ComboBox
有您给定的项目模板。在 ComboBox 的定义中,我添加了 ItemsSource="{Binding Parameters, UpdateSourceTrigger=PropertyChanged}"
。这告诉 ComboBox 它将从位于 VM 中的这个集合中获取它的子项。
VM 中的集合是 ObservableCollection<Parameter>
。这种类型的集合的优点是,它实现了 ICollectionChanged 接口,因此如果有项目添加到此集合或从中删除,您的 V 将得到更新。
V 中的按钮只是向 ObservableCollection<Parameter>
添加了一个虚拟参数。
使用 Command="{Binding AddItemCommand}"
我告诉按钮它的命令-属性 绑定到 DataContext 中的 AddItemCommand。在 DataContext (MainWindow.xaml.cs) 的构造函数中,我正在创建此命令并提供将在执行命令时调用的 AddItem-Method。
DataTemplate 中的 Button 绑定必须提供一个 RelativeSource
因为在 Template 中 DataContext 是另一个。使用 RelativeSource
我可以告诉 Button 它的 Command-属性 绑定到位于 Window.
的 DataContext 中的命令
希望对您有所帮助。
如果您想更深入地了解 MVVM 模式,请查看 this Link
一个快速的方法是将按钮的 Tag
属性 绑定到与 TextBlock
.
相同的 属性
<Button Tag="{Binding Path=Id}" />
然后在按钮单击事件的事件处理程序中,您可以将发送者转换为 Button
并从 Tag
属性.
中获取 ID
int id = Convert.ToInt32((sender as Button).Tag);
我得到了一个模板组合框
<ComboBox x:Name="TryCombo" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="75"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Id}" Margin="4,0" Visibility="Collapsed" Grid.Column="0"/>
<TextBlock Text="{Binding Path=Name}" Margin="4,0" Grid.Column="1"/>
<Button x:Name="AddButton" Content="Add" Grid.Column="2"/>
</Grid>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
然后是 ItemsSource:
public void BindComboboxes()
{
itemMgr.Parameters = RetrieveFilter("");
itemMgr.EntityList = itemMgr.RetrieveMany(itemMgr.Parameters);
TryCombo.ItemsSource = itemMgr.EntityList; //collection;
}
组合框将载入:
我的问题是获取我用 AddButton 单击的选定项目,我想获取绑定到 Path=Id 的文本块的值,但是如何?
我应该为每个 TextBlocks 添加 x:Name 吗?
将您的 Button 绑定到 ViewModel 中的 ICommand-属性 并将所选项目作为 CommandParameter
传递我为您制作了一个小型演示应用程序:
MainWindow.xaml 看起来像:
<Window x:Class="ComboBoxDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Content="Add Item to ComboBox" Margin="5" Command="{Binding AddItemCommand}"/>
<ComboBox Grid.Row="1" x:Name="TryCombo" ItemsSource="{Binding Parameters, UpdateSourceTrigger=PropertyChanged}" Margin="5">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Id}" Margin="4,2" VerticalAlignment="Center" Grid.Column="0"/>
<TextBlock Text="{Binding Path=Name}" Margin="4,2" Grid.Column="1" VerticalAlignment="Center"/>
<Button x:Name="AddButton" Content="Add" Grid.Column="2" VerticalAlignment="Center" Margin="4,2"
Command="{Binding DataContext.ComboBoxItemAddCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
CommandParameter="{Binding}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</Window>
重要的是 Window 声明中的部分:DataContext="{Binding RelativeSource={RelativeSource Self}}"
通过这个你告诉 Window 它的 DataContext 在代码隐藏文件中。您还可以使用另一个文件作为您的 DataContext。比你必须写:
<Window.DataContext>
<loc:MyClassName/>
</Window.DataContext>
这仅在您将 xmlns:loc="clr-namespace:YOURPROJECTNAMESPACE"
添加到 Window 声明时有效。对于我的演示,YOURPROJECTNAMESPACE 将是 ComboBoxDemo。
我还为参数创建了一个 class,它非常简单,看起来像:
public class Parameter
{
public string Id { get; set; }
public string Name { get; set; }
}
Window 的代码隐藏(记住:这是 MainWindow.xaml 的 DataContext)看起来像:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace ComboBoxDemo
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ICommand addItemCommand;
private ICommand comboBoxItemAddCommand;
private ObservableCollection<Parameter> parameters;
public MainWindow()
{
InitializeComponent();
Parameters = new ObservableCollection<Parameter>();
AddItemCommand = new RelayCommand(AddItem);
ComboBoxItemAddCommand = new RelayCommand(ComboBoxItemAdd);
}
private void ComboBoxItemAdd(object parameter)
{
Parameter para = parameter as Parameter;
if (para != null)
{
// Now you can use your Parameter
}
}
public ObservableCollection<Parameter> Parameters
{
get { return parameters; }
set
{
parameters = value;
OnPropertyChanged();
}
}
public ICommand AddItemCommand
{
get { return addItemCommand; }
set
{
addItemCommand = value;
OnPropertyChanged();
}
}
public ICommand ComboBoxItemAddCommand
{
get { return comboBoxItemAddCommand; }
set
{
comboBoxItemAddCommand = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void AddItem(object parameter)
{
Parameters.Add(new Parameter
{
Id = Guid.NewGuid().ToString(),
Name = "Any Name"
});
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
我还创建了一个非常有用的 Helper-Class 如果您使用命令绑定,您可能总是需要它。这是classRelayCommand
。这个 class 有一个构造函数,它需要一个 Action<object>
类型的对象。此操作稍后包含单击按钮时将执行的操作。第二个可选参数我现在不解释。 RelayCommand 看起来像:
using System;
using System.Windows.Input;
namespace ComboBoxDemo
{
public class RelayCommand : ICommand
{
private readonly Action<object> execute;
private readonly Predicate<object> canExecute;
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null )
{
if (execute == null)
throw new ArgumentNullException("execute");
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (canExecute == null)
return true;
return canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
所以。现在我将向您解释该过程:因此,我使用以下缩写
- V = MainWindow.xaml
- VM = MainWindow.xaml.cs
V 中的 ComboBox
有您给定的项目模板。在 ComboBox 的定义中,我添加了 ItemsSource="{Binding Parameters, UpdateSourceTrigger=PropertyChanged}"
。这告诉 ComboBox 它将从位于 VM 中的这个集合中获取它的子项。
VM 中的集合是 ObservableCollection<Parameter>
。这种类型的集合的优点是,它实现了 ICollectionChanged 接口,因此如果有项目添加到此集合或从中删除,您的 V 将得到更新。
V 中的按钮只是向 ObservableCollection<Parameter>
添加了一个虚拟参数。
使用 Command="{Binding AddItemCommand}"
我告诉按钮它的命令-属性 绑定到 DataContext 中的 AddItemCommand。在 DataContext (MainWindow.xaml.cs) 的构造函数中,我正在创建此命令并提供将在执行命令时调用的 AddItem-Method。
DataTemplate 中的 Button 绑定必须提供一个 RelativeSource
因为在 Template 中 DataContext 是另一个。使用 RelativeSource
我可以告诉 Button 它的 Command-属性 绑定到位于 Window.
希望对您有所帮助。
如果您想更深入地了解 MVVM 模式,请查看 this Link
一个快速的方法是将按钮的 Tag
属性 绑定到与 TextBlock
.
<Button Tag="{Binding Path=Id}" />
然后在按钮单击事件的事件处理程序中,您可以将发送者转换为 Button
并从 Tag
属性.
int id = Convert.ToInt32((sender as Button).Tag);