gpt4 book ai didi

c# - 如何在 WPF 中按名称查找样式触发器嵌入元素?

转载 作者:太空宇宙 更新时间:2023-11-03 13:27:16 25 4
gpt4 key购买 nike

首先,问题的核心:如果通过样式触发器将元素指定为 ContentControl 的内容,我似乎无法通过名称找到它。

现在,了解更多详细信息:我有一个面板,其布局和功能根据其数据上下文有很大差异,这是错误库中的错误。当该错误为空时,它是一个搜索表单,当它为非空时,它是该错误属性的简单查看器。 XAML 看起来像这样:

<ContentControl DataContext="...">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Content">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Null}">
<Setter Property="Content">
<StackPanel>
<TextBox Name="Waldo"/>
<Button .../>
</StackPanel>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>

当用户单击位于文本框旁边的按钮时,我会在后面的代码中收到回调。从那时起,我希望能够访问文本框的各种属性。问题是,Waldo 在哪里? :)

在后面的代码中,我尝试了以下几种变体,但都收效甚微:

this.FindName("Waldo"); // Always returns null

我看到很多关于这个话题的讨论,因为它与 templates 相关但与直接使用触发器设置内容无关。也许是因为我这样做违反了各种最佳实践:)

谢谢!

最佳答案

If an element is assigned as the Content of a ContentControl via a style trigger, I can't seem to find it by name.

如果您需要在触发器发生之前访问 Content,这很可能是不可能的。在这种情况下,最主要的事情是在DataTrigger 发生之后获取访问权。

I am violating all sorts of best practices by doing this

也许这不是在 WPF 中使用 Сontrol 的正确方法,您仍然需要访问动态内容,这些内容以后可以更改。但无论如何,有两种方法可以使用 Сontrol - 就像现在和 MVVM 风格。 MVVM 风格最适合具有不同业务逻辑的大型且不太复杂的应用程序。如果您的情况是为了方便应用,在这种情况下,我认为没有任何问题。除了需要从头开始做一个MVVM风格的项目外,将常规方法和正确的方法结合起来并不是一个好方法。

我创建了一个小示例来演示给定情况下的访问控制。有一个属性对应Content的类型,默认是Init。如果您为此属性分配 null,则会加载动态内容。

这就是我访问 TextBox 的方式:

private void GetAccessToTextBox_Click(object sender, RoutedEventArgs e)
{
TextBox MyTextBox = null;
StackPanel panel = MainContentControl.Content as StackPanel;

foreach (object child in panel.Children)
{
if (child is TextBox)
{
MyTextBox = child as TextBox;
}
}

if (MyTextBox != null)
{
MyTextBox.Background = Brushes.Gainsboro;
MyTextBox.Height = 100;
MyTextBox.Text = "Got access to me!";
}
}

下面是一个完整的例子:

XAML

<Window x:Class="AccessToElementInContentControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:AccessToElementInContentControl"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">

<Window.DataContext>
<this:TestData />
</Window.DataContext>

<Window.Resources>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Content">
<Setter.Value>
<Label Content="InitContent"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Setter.Value>
</Setter>

<Style.Triggers>
<DataTrigger Binding="{Binding Path=TypeContent}" Value="{x:Null}">
<Setter Property="Content">
<Setter.Value>
<StackPanel Name="NullStackPanel">
<TextBox Name="Waldo" Text="DynamicText" />
<Button Width="100" Height="30" Content="DynamicButton" />
</StackPanel>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>

<Grid>
<ContentControl Name="MainContentControl" />

<Button Name="SetContentType"
Width="100"
Height="30"
HorizontalAlignment="Left"
Content="SetContentType"
Click="SetContentType_Click" />

<Button Name="GetAccessToButton"
Width="110"
Height="30"
HorizontalAlignment="Right"
Content="GetAccessToTextBox"
Click="GetAccessToTextBox_Click" />
</Grid>
</Window>

代码隐藏

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

private void SetContentType_Click(object sender, RoutedEventArgs e)
{
TestData test = this.DataContext as TestData;

test.TypeContent = null;
}

private void GetAccessToTextBox_Click(object sender, RoutedEventArgs e)
{
TextBox MyTextBox = null;
StackPanel panel = MainContentControl.Content as StackPanel;

foreach (object child in panel.Children)
{
if (child is TextBox)
{
MyTextBox = child as TextBox;
}
}

if (MyTextBox != null)
{
MyTextBox.Background = Brushes.Gainsboro;
MyTextBox.Height = 100;
MyTextBox.Text = "Got access to me!";
}
}
}

public class TestData : NotificationObject
{
private string _typeContent = "Init";

public string TypeContent
{
get
{
return _typeContent;
}

set
{
_typeContent = value;
NotifyPropertyChanged("TypeContent");
}
}
}

public class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

关于c# - 如何在 WPF 中按名称查找样式触发器嵌入元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21977167/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com