2017-09-04 9 views
0

StackPanel、エキスパンダー、テキストボックス、およびいくつかのボタンがあります。例えばボタンと同じコントロールのコントロールから値を取得

私は次のような構造を持っている:私は、ボタンがクリックされたエクスパンダからtextbox.Textを取得できますか

StackPanel 
    Expander 1 
    TextBox 1 
    Button 1 
    Expander 2 
    TextBox 2 
    Button 2 
    Expander 3 
    TextBox 3 
    Button 3 

たとえば、Button 2をクリックして、Expander 2でTextBox 2を取得したいとします。 すべてのコントロールは、StackPanelの代わりにプログラムで追加されます。

イベントのようなものがありますか?同じエキスパンダーでボタンをクリックしたときにテキストボックスを取得する方法がわかりません。

エクスパンダーヘッダーとその内容(例:テキストボックス値)を保存する2つのメソッドが必要です。

第1の方法は、Expander's Headerを右クリックして、ヘッダーをTextBoxに変換してテキストを編集できるようにすることです。 ENTERをクリックすると、TextBox.TextがTextBlockに保存されます。どちらがうまくいくの?しかし、私はボタンのために同じコードを使用することはできません。

Expander editable_expander; // Expander sender from Expander_MouseRightButtonDown 

    private void Expander_MouseRightButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     var ex = sender as Expander; 
     TextBox tb = new TextBox(); 
     tb.Text = ex.Header.ToString(); 
     tb.KeyUp += TextBox_KeyUp; 
     ex.Header = tb; 
     editable_expander = ex; 
    } 

    private void TextBox_KeyUp(object sender, KeyEventArgs e) 
    { 
     // Edit Columnname of selected Column when Enter pressed 
     if (e.Key != Key.Enter) return; 

     var tb = sender as TextBox; 
     e.Handled = true; 


     string old_expander_name = editable_expander.Name.ToString(); 
     string old_column_name = old_expander_name.Split('_')[0]; 

     int length = 0; 
     string type = ""; 

     if(OpenConnection() == true) 
     { 
      try 
      { 
       Grid grid = editable_expander.Content as Grid; 
       List<StackPanel> stackpanel = grid.Children.OfType<StackPanel>().ToList(); 
       for(int i = 1; i < 2; i++) 
       { 
        StackPanel sp = stackpanel[i]; 
        List<TextBox> textbox = sp.Children.OfType<TextBox>().ToList(); 
        for(int j = 0; j < textbox.Count; j++) 
        { 
         TextBox tb1 = textbox[j]; 
         length = Convert.ToInt32(tb1.Text); 
        } 
        List<ComboBox> combobox = sp.Children.OfType<ComboBox>().ToList(); 
        for(int k = 0; k < combobox.Count; k++) 
        { 
         ComboBox cb = combobox[k]; 
         type = cb.Text; 
        } 
       } 

       string query = "ALTER TABLE " + editable_expander.Tag + " CHANGE " + old_column_name + " " + tb.Text + " " + type + "(" + length + ")"; 
       MySqlCommand cmd = new MySqlCommand(query, connection); 
       cmd.ExecuteNonQuery(); 
      } 
      catch (MySqlException ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 
     editable_expander.Header = tb.Text; 
    } 
+0

保存する方法は2つあります。 1がエキスパンダヘッダを右クリックすると、ヘッダがテキストボックスに変換されます。 Enterキーを押すと保存され、TextBlockに戻ります。私は私のトピックでこのメソッドを追加します。しかし、私はテキストボックスイベントで働いているので、私はボタンクリックイベントでこれをもう一度することはできないと思います –

+0

Googleのいくつかのもの..."WPF get parent control"や "WPF get specific child control"のように。 – musefan

+0

私はそれぞれのExpander情報のviewmodelを見たいと思うと思います。こうすることで、プロジェクト全体がコードビハインドで記述されているため、コードアンダーラインで作業しているExpander – kenny

答えて

1

MVVMでこれを行う方法:

XAMLスタイル:

<ItemsControl ItemsSource="{Binding List}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel IsItemsHost="True"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Expander Header="{Binding SomeText}" MinWidth="100"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBox Text="{Binding SomeText}" MinWidth="100"/> 
        <Button MaxWidth="150" Content="ClickMeToGetYourText" Command="{Binding DataContext.ButtonClickedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}}" CommandParameter="{Binding}"/> 
       </StackPanel> 
      </Expander> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

あなたがここに持っていることです:コントロールのリスト:コントロールはStackPanelに配置され、各コントロールが持っています:ExpanderにSomeTextをヘッダーとして追加し、その中に同じテキストのTextBoxとボタンをクリックすることもできます。 Buttonはあなたにあなたのテキストを得るコマンドを持っています。

今C#でいくつかのコード:

のViewModel:あなたがここにあなたがあなたのパンダを作成する元となるリストを、持っている

public class ViewModel 
{ 
    public ObservableCollection<ExpanderData> List { set; get; } = new ObservableCollection<ExpanderData>(); 
    private ICommand _buttonClickedCommand; 
    public ICommand ButtonClickedCommand 
    { 
     get 
     { 
      if (_buttonClickedCommand == null) 
      { 
       _buttonClickedCommand = new RelayCommand(p => ButtonClicked(p)); 
      } 
      return _buttonClickedCommand; 
     } 
    } 

    public void ButtonClicked(Object o) 
    { 
     var expanderData = (ExpanderData)o; 
     var textThatYouWantedToHaveOnButtonClicked = expanderData.SomeText; 
    } 
} 

CommandこれはButtonClickedで何かをすることができ、ButtonClickedイベントで発生するメソッドです。

public class ExpanderData : INotifyPropertyChanged 
{ 
    private string _someText; 

    public string SomeText 
    { 
     set 
     { 
      _someText = value; 
      OnPropertyChanged(); 
     } 
     get 
     { 
      return _someText; 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged([CallerMemberName]string name = null) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
} 
Here you have your Text that is assign to each of your Expander/TextBox, and event that will fire if you want to update your text from code behind. 

そして、あなたはコマンド

public class RelayCommand : ICommand 
{ 
    private Predicate<object> _canExecute; 
    private Action<object> _execute; 

    public RelayCommand(Action<object> execute) 
    { 
     this._canExecute = p => true; 
     this._execute = execute; 
    } 
    public RelayCommand(Predicate<object> canExecute, Action<object> execute) 
    { 
     this._canExecute = canExecute; 
     this._execute = execute; 
    } 

    public event EventHandler CanExecuteChanged 
    { 
     add { CommandManager.RequerySuggested += value; } 
     remove { CommandManager.RequerySuggested -= value; } 
    } 

    public bool CanExecute(object parameter) 
    { 
     return _canExecute(parameter); 
    } 

    public void Execute(object parameter) 
    { 
     _execute(parameter); 
    } 
} 

を結合することを可能にし、これはあなたのビューにVMを追加する方法であるRelayCommandの実装、::

ExpanderDataクラスをどのように見えるか今

var vm = new ViewModel(); 
vm.List.Add(new ExpanderData() { SomeText = "Text1" }); 
vm.List.Add(new ExpanderData() { SomeText = "Text2" }); 
vm.List.Add(new ExpanderData() { SomeText = "Text3" }); 
vm.List.Add(new ExpanderData() { SomeText = "Text4" }); 

this.DataContext = vm; 

また、まだ汚い方法が必要な場合:

private void ButtonClicked(Object sender, ...) 
{ 
    var yourTextBox = ((Panel)((Button)sender).Parent).Children.OfType<TextBox>().First(); 
    var yourText = yourTextBox.Text; 
} 
関連する問題