如何以编程方式更改选项卡控件的索引和索引状态(也许使用命令?)

发布于 2024-08-13 03:52:26 字数 1618 浏览 4 评论 0原文

我有一个 WPF TabControl,其中包含许多带有子 UserControlTabItem,如下所示。

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 用户控件无权访问包含上面显示的 TabControlMainUserControl 。我想出了一个改变 TabControlSelectedIndex 的组合,但这是一个非常丑陋的解决方案,我宁愿做一些更干净的事情。另外,我目前无法更改 SummaryTab 上的 RadioButton

我当前的 C# 技巧:

  Private void btnSummaryDetails_Click(object sender, RoutedEventArgs e)
  {
    TabControl tabControl = UIHelper.FindChild<TabControl>(Application.Current.MainWindow, "tabsMain");
    tabControl.SelectedIndex = 7;
  } 

是否可以使用命令或依赖属性来选择 SummaryTab 和我想要的 RadioButton?我对 WPF 世界还是个新手,并且很想了解更多相关信息。提前致谢。

有关 UIHelper,请参阅我的帖子我在上面的 C# 中使用的定义。

I have a WPF TabControl which contains a number of TabItems with child UserControls, like this.

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>

Within one of the UserControls, lets say, InfoTab, I have a Button. When this Button is clicked I would like to change the index of the TabControl to the SummaryTab and select a radio button on the SummaryTab page.

My problem is that the InfoTab user control does not have access to the MainUserControl which contains the TabControl shown above. I figured out a kludge which changes the SelectedIndex of the TabControl, but this is a very ugly solution and I'd prefer to do something more clean. Also I cannot currently change the RadioButton on my SummaryTab.

My Current C# hack:

  Private void btnSummaryDetails_Click(object sender, RoutedEventArgs e)
  {
    TabControl tabControl = UIHelper.FindChild<TabControl>(Application.Current.MainWindow, "tabsMain");
    tabControl.SelectedIndex = 7;
  } 

Is it possible to use commands or dependency properties to select the SummaryTab and my desired RadioButton? I'm still new to the WPF world, and would love to learn more about this. Thanks in advance.

See my post here for the UIHelper definition I use in the C# above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

懵少女 2024-08-20 03:52:26

脑海中浮现出一个不需要太多改变的想法。

首先,向 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;
}

One thought comes to mind that will not require too many changes.

First, add an event to your InfoTab class:

public event EventHandler SummaryButtonClicked;

Then handle that in your main form by replacing the control declaration with:

<InfoControl:InfoTab x:Name="myInfo" SummaryButtonClicked="summaryButtonClicked" />

And give a name to your SummaryTab:

<SummaryControl:SummaryTab x:Name="summaryTab" />

Then add the event handler in your main form:

void MainWindow_SummaryButtonClicked(object sender, EventArgs e)
{
    this.summaryTab.SelectRadioButton();
}

And add a method in your SummaryTab class to select your radio button.

public void SelectRadioButton()
{
    // TODO: something like
    myRadioButton.IsChecked = true;
}
她比我温柔 2024-08-20 03:52:26

您可能可以使用 WPF 路由事件 来解决您的问题。路由事件使用 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));

    }
}

下一步是将另一个事件沿着可视化树传递,并让其他用户控件侦听它。

You could probably use WPF routed events to solve your problem. Routed events use the WPF visual tree to send events up to parent controls (bubbling) or down to child controls (tunneling) without excessive coupling. I've tried to give a simple example below because I know that routed events can be a bit hairy to learn at first but it's well worth it...

In your main window, define a routed event and add a handler method:

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

    }
}

In your button click handler, raise the event:

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

    }
}

The next step would be to tunnel another event down the visual tree and let the other usercontrol listen for it.

吲‖鸣 2024-08-20 03:52:26

我最终按照杰里米在他的帖子中建议的那样添加了一个公共方法。一个简单但有效的解决方案。谢谢杰里米!

另一个关键实现是,为了按索引切换 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();
  }

然后按照 Jeremy 的建议,我的解决方案类似于:

public void SelectRadioButton()
{
    // TODO: something like
    myRadioButton.IsChecked = true;
}

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

我认为安德鲁·杰克逊的评论绝对有效 - 从长远来看,我计划调查使用路由命令或路由事件来遍历可视树,但现在我坚持使用这种“快速而肮脏”的解决方案,因为我们不运送该产品。根据我的调查,路由事件对于这种情况可能有点矫枉过正。

I ended up adding a public method as Jeremy suggested in his post. A simple but effective solution. Thanks Jeremy!

Another key realization was that in order to switch the tabcontrol by index, I can get a reference to the main user control and set the SelectedItem to the TabItem itself, like this:

  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();
  }

Then as suggested by Jeremy, my solution was something like:

public void SelectRadioButton()
{
    // TODO: something like
    myRadioButton.IsChecked = true;
}

My XAML structure was like

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

I think Andrew Jackson's comments are absolutely valid - long term, I plan to investigate using routed command or routed events to traverse the visual tree, but for now I'm sticking with this "quick and dirty" solution as we're not shipping this product. Based on my investigation Routed Events might be a little overkill for this situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文