WinUI 3 C# 点击UserControl内按钮打开页面SplitView的方法
实现方法
别在UserControl里硬拿页面实例,那种写法耦合太死,改下XAML结构就炸,给你三个能用的方案,按推荐度排序:
方案1:UserControl对外暴露事件(最推荐,无耦合)
这是最符合控件设计规范的写法,UserControl完全不需要知道自己被放在哪个页面里:
- 在自定义UserControl的后台代码里加一个公开事件,内部按钮点击的时候只触发这个事件,不做任何跨控件操作:
// CustomUserControl.xaml.cs public event EventHandler OpenPaneRequest; private void InnerButton_Click(object sender, RoutedEventArgs e) { OpenPaneRequest?.Invoke(this, EventArgs.Empty); }
- 在父页面的ItemsRepeater的DataTemplate里,给你声明的UserControl实例绑定这个事件的处理函数:
<ItemsRepeater ItemsSource="{Binding YourControlCollection}"> <ItemsRepeater.ItemTemplate> <DataTemplate> <local:CustomUserControl OpenPaneRequest="CustomUserControl_OpenPaneRequest"/> </DataTemplate> </ItemsRepeater.ItemTemplate> </ItemsRepeater>
- 在父页面后台的事件处理函数里直接操作当前页的SplitView即可:
// MainPage.xaml.cs private void CustomUserControl_OpenPaneRequest(object sender, EventArgs e) { RootSplitView.IsPaneOpen = true; }
这个写法的好处是控件完全独立,以后你把这个UserControl挪到别的页面、别的容器里,不需要改UserControl内部的任何代码。
方案2:遍历可视化树拿父页面实例(不推荐,仅作兼容)
如果你就是要在UserControl的点击事件里直接拿到父页面,可以写个通用的可视化树查找方法,顺着控件树往上找对应类型的父对象:
// 通用可视化树查找辅助方法 public static T FindVisualParent<T>(DependencyObject element) where T : DependencyObject { var parent = VisualTreeHelper.GetParent(element); if (parent == null) return null; if (parent is T typedParent) return typedParent; return FindVisualParent<T>(parent); } // UserControl内部按钮点击事件 private void InnerButton_Click(object sender, RoutedEventArgs e) { // 把MainPage替换成你自己承载SplitView的页面类名 var hostPage = FindVisualParent<MainPage>(this); // 不要直接把页面的SplitView控件暴露为public,给页面写个公开方法操作SplitView hostPage?.OpenSplitPane(); }
对应的父页面里加个公开方法就行:
public void OpenSplitPane() { RootSplitView.IsPaneOpen = true; }
注意:这个方法维护成本极高,只要你后续调整XAML层级、给UserControl外面多套一层容器,或者把UserControl放到其他页面,这段查找逻辑会直接返回null导致功能失效,非必要不要用。
方案3:消息传递(适合MVVM架构项目)
如果你的项目用了MVVM框架(比如CommunityToolkit.Mvvm),可以直接用弱引用消息机制:UserControl的按钮命令触发时发送一条OpenSplitViewMessage消息,父页面注册监听这条消息,收到后把SplitView的IsPaneOpen设为true即可,整个过程不需要控件之间持有任何引用。
内容的提问来源于stack exchange,提问作者eduardobragaxz
相关产品推荐
相关产品推荐

