C# 如何从ResourceDictionary的代码隐藏中访问UI控件
所以我有一个ResourceDictionary来定义我的自定义窗口样式。我正在努力做的是从XAML文件访问控件。 资源字典看起来像这样C# 如何从ResourceDictionary的代码隐藏中访问UI控件,c#,.net,wpf,xaml,C#,.net,Wpf,Xaml,所以我有一个ResourceDictionary来定义我的自定义窗口样式。我正在努力做的是从XAML文件访问控件。 资源字典看起来像这样 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style x:Key=
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="MyCustomWindowStyle" TargetType="{x:Type Window}">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CaptionHeight="30"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid>
<!-- the root window -->
<Border BorderThickness="0.3" BorderBrush="{DynamicResource GeneralDarkBlue}">
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
</Border>
<DockPanel Height="30" Background="{TemplateBinding Background}" VerticalAlignment="Top" LastChildFill="False">
<Viewbox x:Name="HamburgerMenu" DockPanel.Dock="Left" WindowChrome.IsHitTestVisibleInChrome="True">
<Viewbox.InputBindings>
<MouseBinding MouseAction="LeftClick" Command="{Binding SettingsClick}"/>
</Viewbox.InputBindings>
<Border Width="47" Height="32" Background="Transparent">
<Canvas>
<Path x:Name="TopbarIconHamburgerMenu" Margin="14,10" Data="M12.5,19h19.2v1H12.5V19z M12.5,13.7h19.2v1H12.5V13.7z M12.5,8.5h19.2v1H12.5V8.5z" Stretch="UniformToFill" Fill="#FFFFFF"/>
</Canvas>
</Border>
</Viewbox>
// the rest of viewboxes for minimize, maximize controls...
</DockPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
public partial class MyCustomWindowStyle : ResourceDictionary
{
public MyCustomWindowStyle()
{
InitializeComponent();
}
public void DoSomething()
{
var window = (Style)Application.Current.Resources["MyCustomWindowStyle"];
var hm = (Viewbox)window.Resources.FindName("HamburgerMenu");
}
}
这在hm中返回null
你知道怎么做吗?首先,
风格。Resource
是一个资源字典
,在资源字典中有两件重要的事情需要注意。FindName
方法:
摘要部分说:
此字典实现不支持
和返回值部分,说明:
始终返回null
其次,即使您尝试按键检索查看框
,也必须将其定义为资源:
<Style x:Key="MyCustomWindowStyle" TargetType="{x:Type Window}">
<Style.Resources>
<ViewBox x:Key="HamburgerMenu" />
</Style.Resources>
</Style>
<Style x:Key="MyCustomWindowStyle" TargetType="{x:Type Window}">
<Style.Resources>
<ControlTemplate x:Key="Template" TargetType="{x:Type Window}">
<Grid>
(...)
<ViewBox x:Key="HamburgerMenu" />
(...)
</Grid>
</ControlTemplate>
</Style.Resources>
<Setter Property="Template" Value="{StaticResource Template}" />
</Style>
那么,这应该对您有帮助:
var window = (Style)Application.Current.Resources["MyCustomWindowStyle"];
var template = (ControlTemplate)window.Resources["Template"];
var root = (FrameworkElement)template.LoadContent();
var hm = (ViewBox)root.FindName("HamburgerMenu");
更新 如果您的目标是在应用了该模板的现有窗口中获得
ViewBox
,那么首先您需要知道如何获得该特定窗口。它可能是Application.Current.main窗口
,否则很可能在Application.Current.Windows
集合中找到它。您还可以为该窗口实现单例模式,或者使用其他方法,例如在应用程序中的某个位置公开引用该窗口的静态属性,或者使用第三方工具,例如在Prism中
一旦您手中有了窗口,您只需要使用前面提到的ControlTemplate.FindName
方法:
var window = (...);
var hm = (ViewBox)window.Template.FindName(name: "HamburgerMenu", templatedParent: window);
请注意,不需要访问在其中定义模板的资源字典
至于您尝试使用以前的解决方案失败的原因,这是因为每次调用
ControlTemplate.LoadContent
方法时都会生成新创建的元素,修改它不会反映以前由该模板创建的元素。是否已将生成操作设置为资源?MyCustomWindowStyle.xaml已设置为页面生成操作。并且MyCustomWindowStyle.xaml.cs设置为编译。如果我将第一个设置为Resource,则会出现错误“名称'InitializeComponent'在当前上下文中不存在”“HamburgerMenu”不在样式的资源列表中。它是ControlTemplate中的子元素。因此,在进入“汉堡菜单”之前,您必须通读ControlTemplate中的子网格。希望这有帮助@Fireboyd78谢谢你的评论,但这没什么帮助,因为我不知道怎么做!非常感谢您的时间和非常好的解释。然而,仍然存在一些问题。首先,我仍然无法在Viewbox中设置x:Key。我得到错误“key属性只能在IDictionary中使用”。但是我留下了x:Name,代码也起作用了。。。直到我试图设置hm.Visibility=Visibility.Hidden;它什么也没做!它没有隐藏控制。我是遗漏了什么还是误解了?是的,我想你误解了模板的工作原理。正如我所说,模板基本上是创建可视化树的方法,它只“知道”如何创建这样的可视化树,而不知道如何在应用程序的深渊中找到以前创建的树。作为一名程序员,您需要跟踪这些信息。看到我更新的答案。我承认我还有很多关于XAML、模板等的知识要学习。非常感谢你的回答@Grx70我发布了类似的问题-以防您有时间提出建议/意见或解决方案。非常感谢。