繁体   English   中英

获取并操作 WPF 中动态添加的控件

[英]Get and act on dynamically-added controls in WPF

我正在基于描述控件各种设置的字典以编程方式添加一系列控件。 这里有两个条目作为示例(我截断了 rest 以节省空间):

    // Translation array from fix shortname to various data about them
        private Dictionary<string, Dictionary<string, string>> fixers = new Dictionary<string, Dictionary<string, string>>
        {
            ["F1"] = new Dictionary<string,string> {
                ["PrefName"] = "KillF1UnhelpfulHelp",
                ["Img"] = @"/graphics/F1key.png",
                ["Title"] = @"Diable F1 ""Help"" function",
                ["Description"] = @"
                    Have you ever hit the F1 key by accident and had a distracting and unhelpful window or webpage open as a result? 
                    Windows set the F1 key to a generic help function that basically never helps and always gets in the way. 
                    Enable this control to disable that obnoxious design choice. Note that some programs still respond to F1 on their own accord, 
                    but this will stop the default Windows behavior in things like Windows Explorer at least.
                    ",
                ["Tags"] = "#Keyboard,#Rage"
            },
            ["CMD"] = new Dictionary<string, string>
            {
                ["PrefName"] = "RestoreAdminCMDContext",
                ["Img"] = @"/graphics/CMD.png",
                ["Title"] = @"Restore ""Open Admin CMD Window Here"" to Windows Explorer",
                ["Description"] = @"
                    When you need to run commands in CMD, it's usually in a specific folder. Windows used to have an option when you CTRL+Right Click 
                    to show ""Open CMD HERE"" on a folder. This restores that function AND it's at administrative level (and you don't need to CTRL+CLICK to see it)
                    ",
                ["Tags"] = "#Windows Explorer,#TimeSaver"
            },
}

控件本身只是带有一些网格组件、按钮等的自定义框。相当简单。 它们目前正确生成,然后添加到 window 中,如下所示:

添加它们的代码:

        public MainWindow()
        {
            InitializeComponent();
            var fixNames = fixers.FixerNames();
            foreach (string key in fixNames)
            {
                var temp = fixers.GetFix(key);
                // Be sure to pass this along as well
                temp["Name"] = key;
                fixerBoxes[key] = new FixerBox(temp);
                FixersArea.Children.Add(fixerBoxes[key]);
            }

            FixerBox f1box = (FixerBox)FixersArea.FindName("F1");
            StatusBox.Text += "Tags are:"+ f1box.FixerTags;
        }

这是添加控件的 window 的 XAML:

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition />
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Name="StatusBox" Width="600" MinHeight="40" Background="Beige"/>
        <ScrollViewer Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Visible">
            <WrapPanel Name="FixersArea" Orientation="Horizontal" Width="auto" ></WrapPanel>
        </ScrollViewer>

    </Grid>

这是 output:

使用自定义控件呈现的主窗口

一切都按预期工作,但是如何引用动态生成的自定义控件? 我尝试了几种通过名称或其他值引用它的方法,并通过将一些文本打印到状态框来进行测试:


            FixerBox f1box = (FixerBox)FixersArea.FindName("F1");
            StatusBox.Text += "Tags are:" + f1box.FixerTags;

但这会导致出现异常,指出 f1box 是 null。因此查找器无法正常工作。 我在网上找到了一些通过名称查找子元素的方法,但这些方法也没有用,而且相当长,所以我将它们排除在外。

最重要的是,我需要获取/设置控件的 state,根据过滤器显示和隐藏它们,并响应它们的点击事件。 我可能可以处理控件本身的点击响应,但 rest 肯定会成为主窗口的东西(控件将受到过滤和各种保存/加载设置的影响)。

FindName方法使用 Xaml 中的x:Name值来查找子项。 如果你需要一个动态添加的孩子通过FindName可用,你需要在 C# 中显式注册它的名字:

FixersArea.RegisterName(key, fixerBoxes[key]);

然后你可以使用下面的代码来检索孩子:

FixerBox f1box = (FixerBox)FixersArea.FindName("F1");

但是,由于您已经维护了 fixerBoxes 的字典,您可以这样做:

FixerBox f1box = fixerBoxes["F1"];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM