我有一个WPF TabControl
,其中包含许多TabItem
个带有UserControl
个孩子的内容,就像这样。
XAML:
<TabControl x:Name="tabsMain" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Grid.Row="0" Grid.RowSpan="3" Background="lightgray">
<TabItem Width="100" Header="Profile" FontSize="16">
<InfoControl:InfoTab x:Name="myInfo" />
</TabItem>
<TabItem Width="120" x:Name="Summary" Header="Summary" FontSize="16">
<SummaryControl:SummaryTab/>
</TabItem>
</TabControl>
在其中一个UserControl
中,让我们说InfoTab
,我有一个Button
。单击此Button
后,我想将TabControl
的索引更改为SummaryTab
,然后在SummaryTab
页面上选择一个单选按钮。
我的问题是,InfoTab
用户控件无法访问包含上面显示的MainUserControl
的{{1}}。我想出了一个改变TabControl
的{{1}}的kludge,但这是一个非常难看的解决方案,我宁愿做一些更干净的事情。此外,我目前无法更改SummaryTab上的SelectedIndex
。
My Current C#hack:
TabControl
是否可以使用命令或依赖项属性来选择RadioButton
和我想要的 Private void btnSummaryDetails_Click(object sender, RoutedEventArgs e)
{
TabControl tabControl = UIHelper.FindChild<TabControl>(Application.Current.MainWindow, "tabsMain");
tabControl.SelectedIndex = 7;
}
?我还是WPF世界的新手,并希望了解更多相关信息。提前致谢。
有关我在上述C#中使用的SummaryTab
定义,请参阅my post here。
答案 0 :(得分:1)
我想到了一个不需要太多改变的想法。
首先,向InfoTab类添加一个事件:
public event EventHandler SummaryButtonClicked;
然后通过将控制声明替换为:
来处理主窗体中的声明<InfoControl:InfoTab x:Name="myInfo" SummaryButtonClicked="summaryButtonClicked" />
并为SummaryTab命名:
<SummaryControl:SummaryTab x:Name="summaryTab" />
然后在主窗体中添加事件处理程序:
void MainWindow_SummaryButtonClicked(object sender, EventArgs e)
{
this.summaryTab.SelectRadioButton();
}
在SummaryTab类中添加一个方法来选择单选按钮。
public void SelectRadioButton()
{
// TODO: something like
myRadioButton.IsChecked = true;
}
答案 1 :(得分:1)
您可以使用WPF routed events来解决您的问题。路由事件使用WPF可视树将事件发送到父控件(冒泡)或向下发送到子控件(隧道),而不会过度耦合。我试着在下面给出一个简单的例子,因为我知道路线事件起初可能有点毛茸茸,但值得一试......
在主窗口中,定义路由事件并添加处理程序方法:
public partial class MainWindow : Window {
public static RoutedEvent ClickedEvent = EventManager.RegisterRoutedEvent(
"Clicked",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MainWindow));
public MainWindow() {
InitializeComponent();
this.AddHandler(MainWindow.ClickedEvent, new RoutedEventHandler(OnClickedEvent));
}
public void OnClickedEvent(object sender, RoutedEventArgs e) {
// do your work here
}
}
在按钮单击处理程序中,引发事件:
public partial class UserControl1 : UserControl {
public UserControl1() {
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e) {
// raise the event (gets bubbled up to the parent of the control)
this.RaiseEvent(new RoutedEventArgs(MainWindow.ClickedEvent));
}
}
下一步是将另一个事件沿着可视树进行隧道传输,让另一个用户控件监听它。
答案 2 :(得分:0)
我最后添加了一个公共方法,就像杰里米在他的帖子中所说的那样。简单但有效的解决方案。谢谢杰里米!
另一个关键的实现是,为了通过索引切换tabcontrol,我可以获得对主用户控件的引用,并将SelectedItem设置为TabItem本身,如下所示:
Private void btnSummaryDetails_Click(object sender, RoutedEventArgs e)
{
//HACK replace this with a command that toggles to a different tab instead of this tab reference
MainUserControl mainUserControl = UIHelper.FindChild<MainUserControl>(Application.Current.MainWindow, "root");
mainUserControl.tabsMain.SelectedItem = mainUserControl.Summary;
mainUserControl.SummaryUserControl.SelectRadioButton();
}
然后正如杰里米所说,我的解决方案就像:
public void SelectRadioButton()
{
// TODO: something like
myRadioButton.IsChecked = true;
}
我的XAML结构就像
// my main user control:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
x:Name="root"
>
<TabControl x:Name="tabsMain" ...>
<TabItem x:Name="Summary" ... />
</TabControl>
</UserControl>
我认为Andrew Jackson的评论绝对有效 - 长期来看,我打算调查使用路由命令或路由事件来遍历可视树,但是现在我坚持使用这个“快速而肮脏”的解决方案,因为我们是不发货此产品。根据我的调查,路线事件对于这种情况可能有点过分。