基于此XAML
,
<ListView>
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock Text="{Binding ProductDescription}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBox x:Name"txtExchange"
Tag="{Binding ProductBarcode}"/>
<Button Content="Add"
Tag="{Binding ProductBarcode}"
Click="SelectExchangeProduct" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
由于插入的所有行都具有相同的TextBox
,因此使用x:Name
来获取值是不可能的。
我添加了绑定到Tag
属性,以便我可以区分所有TextBox
。问题是如何才能找到具体的TextBox
?我尝试使用FindName()
,但我不知道如何使用特定TextBox
值获取Tag
。
我也试过这个:
var txtExchangeQuantity = someParentControl.Children.OfType<TextBox>().Where(x => x.Tag.ToString() == barcode).FirstOrDefault();
但也没用。我看到了Where
部分的潜力,但不知道如何实现它。
以下是Click
事件:
private void SelectExchangeProduct(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
string barcode = btn.Tag.ToString();
var txtExchangeQuantity = grdExchange.Children.OfType<TextBox>().Where(x => x.Tag.ToString() == barcode).FirstOrDefault();
}
以下是我绑定到的对象(使用ObservableCollection
):
class TransactionList{
private string _productBarcode;
public string ProductBarcode
{
get { return _productBarcode; }
set { _productBarcode = value; }
}
private string _productDescription;
public string ProductDescription
{
get { return _productDescription; }
set { _productDescription = value; }
}
}
答案 0 :(得分:1)
在代码中的某处创建ICommand
的实现,如下所示:
public class RelayCommand : ICommand
{
#region Fields
private Action<object> execute;
private Predicate<object> canExecute;
#endregion
#region Events
public event EventHandler CanExecuteChanged;
#endregion
#region Constructors
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
this.execute = execute ?? throw new ArgumentException(nameof(execute));
this.canExecute = canExecute ?? throw new ArgumentException(nameof(canExecute));
}
#endregion
#region Methods
public void InvokeExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
public bool CanExecute(object parameter)
{
return canExecute(parameter);
}
public void Execute(object parameter)
{
execute(parameter);
}
#endregion
}
然后,您可以在视图模型中实现属性,如
public RelayCommand SelectExchangeProductCommand { get; private set; }
public ViewModel()
{
SelectExchangeProductCommand = new RelayCommand(SelectExchangeProductExecute, SelectExchangeProductCanExecute);
}
然后实现了两种方法:
public void SelectExchangeProductExecute(object parameter)
{
// parameter will then be your Barcode
if(parameter is string barcode)
{
// Now you have the barcode available... but you can really bind anything to end up here.
}
}
public bool SelectExchangeProductCanExeucte(object parameter)
{
// return true and false accordingly to execution logic. By default, just return true...
return true;
}
然后你可以在xaml中将Button绑定到这个命令,如下所示:
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBox x:Name"txtExchange" />
<Button Content="Add"
Command="{Binding Source=ViewModel, Path=SelectExchangeProductCommand}"
CommandParameter="{Binding ProductBarcode}" />
</StackPanel>
</DataTemplate>
就像这样,您无需识别Button
或TextBox
,只需将相应数据绑定到CommandParameter
,模板即可完成其余工作。
答案 1 :(得分:0)
似乎ICommand是要走的路,但对我来说这是一个新概念,所以我会告诉你在我的案例中我会做些什么:
UserControl中的组控件&#34; ExchangeControl&#34;用例如。一个TextBox&#34; txtExchange&#34;,一个Button&#34; btnAdd&#34;和一个事件所以当你点击btnAdd时,你可以完全控制txtExange做一些事情。
在需要时实例化:
someStackPanel.Children.Add(new ExchangeControl() {Content = "SOME TEXT"});
要让上述代码有效,您应该在ExchangeControl类中拥有此属性:
private string content;
public string Content
{
get { return content; }
set { content = value; txtExchange.Text = value; }
}
所以......现在你可以通过点击btnAdd来获取txtExchange内容(SOME TEXT),如果你在ExchangeControl类中点击按钮创建了一个事件
只是为了图表,这里是一个向您的按钮添加事件的示例,假设已经有一个带有一些ExchangeControl项目的StackPanel
someStackPanel.Children.Cast<ExangeControl>().ToList().ForEach(ec =>
ec.btnAdd.Click += (se, a) => MessageBox.Show(ec.txtExchange.Text));
顺便说一句,这里是如何在选中时获取DataGrid中特定TextBox的内容:
string someContent = (yourDataGrid.SelectedItem as TextBox).Text;
答案 2 :(得分:-2)
使用VisualTreeHelper按类型获取子项更容易。