2017-08-04 10 views
0

的標記值,充分利用這個<code>XAML</code>基於控制

<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(),但我不知道如何獲得具有特定Tag值的TextBox

我也試過這樣:

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; } 
    } 
} 
+5

你不知道。這是WPF,而不是WinForms。使用[命令](https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/commanding-overview)而不是點擊處理程序。您可以將文本作爲參數傳遞。 – nvoigt

+0

我想'grdExchange.Children'只有堆疊面板。你的情況很好。 – rmbq

+0

grdExchange是一個擁有這個ListView和其他子元素的Grid。我省略了,因爲我不認爲這是必要的。它只是具有'.Children'的最近控件。 – Swellar

回答

1

制定實施Ø ˚FICommand地方在你的代碼是這樣的:

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中的此命令,如下所示:

<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> 

而且像這樣,你不需要識別ButtonTextBox,只需將各自的數據綁定到CommandParameter,模板將完成剩下的工作。

+0

有了這個,我可以綁定'txtExchange'的'Text'值嗎? – Swellar

+0

@Swellar是的。你當然也可以將'CommandParameter'綁定到任何可綁定的東西。最壞的情況:你需要'Text'屬性和條形碼。因此,將文本綁定到包含條形碼的同一個對象,並將該整個對象綁定爲「CommandParameter」而不僅僅是一個屬性。正如你在實現中看到的那樣,參數可以是任何對象。 – Adwaenyth

+0

因此,有可能使用它來區分'textbox'的'Tag'值對應於'button'的'Tag'值嗎?這只是我之前沒有使用過Commands,而你的回答對我來說很陌生 – Swellar

0

似乎是的ICommand要走的路,但是這是一個新的概念給我,讓我來告訴你我會在你的情況做:

在用戶控件組控制「ExchangeControl」與例如。一個文本框「txtExchange」,一個按鈕「btnAdd」和一個事件,所以當你點擊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的內容(如果你創建了一個事件到你的ExchangeControl類中的按鈕點擊)

只是爲了圖形,下面是一個添加事件到你的按鈕的例子,假設已經有一個StackPanel一些ExchangeControl項目

someStackPanel.Children.Cast<ExangeControl>().ToList().ForEach(ec => 
    ec.btnAdd.Click += (se, a) => MessageBox.Show(ec.txtExchange.Text)); 

順便說一句,這裏的選擇時如何獲得在DataGrid中特定的文本框的內容:

string someContent = (yourDataGrid.SelectedItem as TextBox).Text;