无法在 WPF 中检索动态生成的按钮的内容
Posted
技术标签:
【中文标题】无法在 WPF 中检索动态生成的按钮的内容【英文标题】:Failing To Retrieve Content of Dynamically Generated Button in WPF 【发布时间】:2012-10-13 09:20:38 【问题描述】:我正在开发一个 WPF 应用程序。我基本上是一名 C++ 开发人员,最近转向 C#。在我的应用程序中,我动态生成了一组执行特定操作的按钮。
每个按钮都有一个频率,它被捕获并用于执行某些操作。在我的 C++ 应用程序中,我创建如下:
static const char *freqs[MAX_CLOCK_RANGE] =
"12.0.",12.288","15.36","19.2","23.0","24.0","26.0" //MAX_CLOCK_RANGE is 7
;
for(int i = 0; i < MAX_CLOCK_RANGE; i++)
buttonText = String(T("Set ")) + String(freqs[i])+ String(T(" MHz"));
m_buttonSetFreq[i] = new TextButton(buttonText, String::empty);
m_buttonSetFreq[i]->addButtonListener(this);
addAndMakeVisible(m_buttonSetFreq[i]);
int cnt = 0;
while(cnt < MAX_CLOCK_RANGE)
if(button == m_buttonSetFreq[cnt])
break;
cnt++;
if(cnt < MAX_CLOCK_RANGE)
unsigned int val = String(freqs[cnt]).getDoubleValue() * 1000.0;
sendBuf[numBytes++] = 0x00; //SendBuf is unsigned char
sendBuf[numBytes++] = 0x00;
sendBuf[numBytes++] = (val >> 8) & 0xFF;
sendBuf[numBytes++] = val & 0xFF;
因此,它从 char 数组中获取 freq 的值并对其执行上述操作。 Cnt 具有单击哪个特定按钮的值,并采用单击按钮的频率。我在我的 WPF 应用程序中按如下方式进行:
XAML:
<ListBox x:Name="SetButtonList" ItemsSource="Binding" >
<ListBox.ItemTemplate>
<DataTemplate >
<Grid>
<Button Name="FreqButton" Content="Binding Path=SetButtonFreq" Command="Binding ElementName=SetButtonList, Path=DataContext.SetFreqCommand" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Xaml.cs:
ClockViewModel mClock = new ClockViewModel();
mClock.Add(new ClockModel("Set 12.0 MHz"));
mClock.Add(new ClockModel("Set 12.288 MHz"));
mClock.Add(new ClockModel("Set 15.36 MHz"));
mClock.Add(new ClockModel("Set 19.2 MHz"));
mClock.Add(new ClockModel("Set 23.0 MHz"));
mClock.Add(new ClockModel("Set 24.0 MHz"));
mClock.Add(new ClockModel("Set 26.0 MHz"));
SetButtonList.DataContext = mClock;
视图模型:
ClockModel mCModel = new ClockModel();
private ICommand mSetFreqCommand;
public ICommand SetFreqCommand
get
if (mSetFreqCommand == null)
mSetFreqCommand = new DelegateCommand(new Action(SetFreqCommandExecuted), new Func<bool>(SetFreqCommandCanExecute));
return mSetFreqCommand;
set
mSetFreqCommand = value;
public bool SetFreqCommandCanExecute()
return true;
public void SetFreqCommandExecuted()
//How can I retrieve the Frequency of button clicked and perform same operation as done in C++
型号:
public String SetButtonFreq get; set;
是否可以获取每个按钮的点击频率并执行与 C++ 代码中相同的步骤???请帮忙:)
【问题讨论】:
【参考方案1】:两种可能的解决方案。
第一个:绑定到每个按钮的 ViewModel 实例中的命令:
<Window x:Class="WpfTest.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">
<Grid>
<ListBox ItemsSource="Binding Clocks">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="Binding Frequency"
Command="Binding SetFrequency"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
使用以下视图模型和代码:
class ClockViewModel // DataContext of ListBoxItem
public double Frequency get; set;
public ICommand SetFrequency
get
return new DelegateCommand((obj) =>
double freq = this.Frequency;
// ...
);
class WindowViewModel
ObservableCollection<ClockViewModel> clocks_ =
new ObservableCollection<ClockViewModel>();
public ObservableCollection<ClockViewModel> Clocks get return clocks_;
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
var viewModel = new WindowViewModel();
viewModel.Clocks.Add(new ClockViewModel() Frequency = 10.123 );
viewModel.Clocks.Add(new ClockViewModel() Frequency = 42.0 );
viewModel.Clocks.Add(new ClockViewModel() Frequency = 3.14 );
DataContext = viewModel;
2nd):如果命令应该是 windows 视图模型的一部分,您可以使用 CommandParameter
(更新为以“Set 3.13 Mhz”格式显示):
<Window x:Class="WpfTest.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">
<Grid>
<ListBox Name="list" ItemsSource="Binding Clocks">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Command="Binding Path=DataContext.SetFrequency,
ElementName=list"
CommandParameter="Binding">
<Button.Content>
<TextBlock>
<Run>Set </Run>
<Run Text="Binding Frequency"/>
<Run> Mhz</Run>
</TextBlock>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
这会将按钮数据上下文传递给命令:
class ClockViewModel
public double Frequency get; set;
class WindowViewModel
ObservableCollection<ClockViewModel> clocks_ = new ObservableCollection<ClockViewModel>();
public ObservableCollection<ClockViewModel> Clocks
get return clocks_;
public ICommand SetFrequency
get
return new DelegateCommand((obj) =>
var clock = obj as ClockViewModel;
DoSendBufStuffWithFrequency(clock.Frequency);
);
private void DoSendBufStuffWithFrequency(double frequency)
【讨论】:
感谢您的回复。在你的第一种方法中,频率值应该在哪里硬编码???你能编辑你的答案并添加它吗:) @StonedJesus 这些值将在您的业务层中定义,或者从数据库或其他地方加载。当您显示该窗口时,您将为业务层中的每个 ClockModel 创建一个 ClockViewModel 实例,并将其添加到 ObservableCollection。如果这些值只是纯 GUI 问题,您可以在 ViewModel 中定义它们,或者如果它们是静态的,您可以在 XAML 中使用 DataProvider。这取决于您的应用程序详细信息... 尝试了你的第一种方法,但是当我运行应用程序时没有一个按钮是可见的 @StonedJesus 我添加了一个完整的(最小)示例。 @StonedJesus 我再次阅读了您的原始问题,我现在认为您想使用第二种解决方案。我在第二个解决方案示例中添加了“设置 xx Mhz”格式。如果 ClocjViewModel 除了 Frequancy 之外没有其他属性,您可以摆脱该类并将这些值直接存储在MainWindowViewModel
以上是关于无法在 WPF 中检索动态生成的按钮的内容的主要内容,如果未能解决你的问题,请参考以下文章
C#(wpf)中动态button单击事件取的动态生成的textbox中的内容
WPF/Silverlight的问题:在后台代码动态生成的控件,怎么设置动态样式 Style="DynamicResource sbStyle