我有一个StackPanel,一些Expanders,一些文本框和一些按钮。
例如,我有以下结构:
StackPanel
Expander 1
TextBox 1
Button 1
Expander 2
TextBox 2
Button 2
Expander 3
TextBox 3
Button 3
如何从点击按钮的Expander中获取textbox.Text?
例如,我单击按钮2,我想在Expander 2中获取TextBox 2。 所有控件都是以编程方式添加的,而不是StackPanel。
有什么类似事件吗?在同一个扩展器中单击按钮时,我不知道获取文本框的方法。
我想要两种方法来保存我的Expander Header及其内容(例如文本框值)。
第一种方法是右键单击Expander的Header,它将Header转换为TextBox,这样我就可以编辑文本了。通过单击ENTER,它将TextBox.Text保存到TextBlock中。哪个工作正常。但我不能使用相同的代码来实现Button。
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 :(得分: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作为标题,然后在其中,还有{{ 1}}具有相同的文本和按钮,您可以单击。 TextBox
有命令,你可以在其中获取文字。
现在C#中的一些代码:
ViewModel:
Button
您有此列表,您可以从中创建扩展器。 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
事件中触发的方法。
现在,看看ExpanderData类:
ButtonClicked
和RelayCommand实现,它允许您绑定命令
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.
这就是您可以在视图中添加VM的方法:
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);
}
}
或者,如果你还想要一些肮脏的方式:
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;