我在这里有一个模板组合框
<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吗?
答案 0 :(得分:1)
将Button绑定到ViewModel中的ICommand-Property并将所选项目作为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-Declaration中的部分:DataContext="{Binding RelativeSource={RelativeSource Self}}"
通过这个,你告诉Window它的DataContext在CodeBehind-File中。您还可以使用另一个File作为DataContext。比你必须写:
<Window.DataContext>
<loc:MyClassName/>
</Window.DataContext>
这仅适用于将xmlns:loc="clr-namespace:YOURPROJECTNAMESPACE"
添加到Window-Declaration中的情况。在我的演示的情况下,YOURPROJECTNAMESPACE将是ComboBoxDemo。
我还为参数创建了一个非常简单的类,如下所示:
public class Parameter
{
public string Id { get; set; }
public string Name { get; set; }
}
Window的CodeBehind(记住:这是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,如果你使用命令绑定,你可能总是需要它。这是班级RelayCommand
。这个类有一个构造函数,它需要一个Action<object>
类型的对象。稍后此操作包含单击按钮时将执行的操作。 seconde可选参数我现在不解释。 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中的ComboBox
具有您给定的Itemtemplate。在ComboBox的定义中,我添加了ItemsSource="{Binding Parameters, UpdateSourceTrigger=PropertyChanged}"
。这告诉ComboBox它将从这个位于VM中的集合中获取它的子节点。
VM中的集合是ObservableCollection<Parameter>
。这种类型的Collection的优点是,它实现了ICollectionChanged-Interface,因此如果在此集合中添加或删除了项目,V将会更新。
V中的Button只是将一个虚拟参数添加到ObservableCollection<Parameter>
。
使用Command="{Binding AddItemCommand}"
我告诉Button它的命令属性绑定到DataContext中的AddItemCommand。在DataContext(MainWindow.xaml.cs)的构造函数中,我正在创建此命令并提供AddItem-Method,如果执行该命令将调用该方法。
DataTemplate中Button的绑定必须提供RelativeSource
,因为在Template中DataSetext是另一个。使用RelativeSource
我可以告诉Button它的Command-Property绑定到位于Window的DataContext中的Command。
我希望这会对你有所帮助。
如果您想深入了解MVVM模式,请查看this Link
答案 1 :(得分:1)
一种快速的方法是简单地将按钮的Tag
属性绑定到与TextBlock
相同的属性。
<Button Tag="{Binding Path=Id}" />
然后在按钮点击事件的事件处理程序中,您可以将发件人强制转换为Button
并从Tag
属性中获取ID。
int id = Convert.ToInt32((sender as Button).Tag);