如何在WPF中按名称查找样式触发器嵌入元素? [英] How can I find a style trigger-embedded element by name in WPF?

查看:78
本文介绍了如何在WPF中按名称查找样式触发器嵌入元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

现在,更多细节:我有一个面板,该面板的布局和功能根据其数据上下文而有很大不同,这是来自错误库的一个错误。当该错误为null时,它是一个搜索表单;当该错误为非null时,它是该错误属性的简单查看器。 XAML如下所示:

Now, for more detail: I have a panel that varies greatly in its layout and functionality based on its data context, which is a bug from a bug depot. When that bug is null, it is a search form, when it is non-null, it is a simple viewer for properties of that bug. The XAML then look something like:

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

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

When the user clicks the button that sits alongside the text box, I get a callback in the code behind. From that point I'd like to be able to access various properties of the text box. The question is, where's Waldo? :)

在后面的代码中,我尝试了以下几种变体,但都没有成功:

In the code behind I have tried a few variants of the following, all with little success:

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

由于与<一个href = https://stackoverflow.com/questions/820201/how-to-access-a-wpf-control-located-in-a-controltemplate>模板,但与设置内容无关直接使用触发器。也许是因为这样做违反了所有最佳做法:)

I've seen a lot of discussion on this topic as it relates to templates but not as it relates to setting content directly with triggers. Maybe it's because I am violating all sorts of best practices by doing this :)

谢谢!

推荐答案


如果将元素分配为 ContentControl Content $ c>通过样式触发器,我似乎无法按名称找到它。

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之后获得访问权的主要事情。

If you needed to access to the Content before trigger occurs, it would most likely not possible. In this situation, the main thing to get access after the DataTrigger occurs.


我这样做违反了所有最佳实践

I am violating all sorts of best practices by doing this

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

Maybe it's not the right way to work with the Сontrol in WPF, the more that you still need access to dynamic content, which can later be changed. But in any case, there are two ways to work with the Сontrol - it's like now and in the MVVM style. MVVM style is best suited for large and less complex applications with different business logic. If in your case for easy application, in this situation, I do not see anything wrong with that. In addition to doing a project in MVVM style need from scratch, combine conventional method and the correct method is not a good way.

我创建了一个小示例来演示访问控制对于给定的情况。有一个与内容类型相对应的属性,默认值为 Init 。如果为该属性分配 null ,则将加载动态内容。

I created a small example to demonstrate access controls for a given situation. There is a property that corresponds to the type of Content, the default is Init. If you assigns null for this property, the dynamic Content is loaded.

这就是我访问 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!";
    }
}

下面是一个完整的示例:

Below it's a full example:

XAML

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>

隐藏代码

Code-behind

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

这篇关于如何在WPF中按名称查找样式触发器嵌入元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆