【问题标题】:Get and act on dynamically-added controls in WPF获取并处理 WPF 中动态添加的控件
【发布时间】:2021-10-04 11:30:44
【问题描述】:

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

    // 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"
            },
}

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

添加它们的代码:

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

这是添加控件的窗口的 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>

这是输出:

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


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

但这会导致一个异常,指出 f1box 为空。所以取景器不工作。我在网上找到了一些按名称查找子元素的方法,但这些方法也不起作用,而且相当长,所以我将它们排除在外。

底线是我需要获取/设置控件的状态,根据过滤器显示和隐藏它们,并响应它们的点击事件。我可能可以在控件本身中处理点击响应,但其余部分肯定是主窗口的东西(控件将受到过滤和各种保存/加载设置的影响)。

【问题讨论】:

  • 为什么不f1box = fixerBoxes["F1"]
  • 我刚才自己就想通了。我从 HTML 的角度来看这个太多了。它工作正常。如果您将其发布为答案(基本上停止引用“文档”并引用现有对象),我会接受它。

标签: c# wpf


【解决方案1】:

FindName 方法使用 Xaml 中的 x:Name 值来查找子级。如果您需要通过FindName 提供动态添加的子项,则需要在 C# 中显式注册其名称:

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

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

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

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

FixerBox f1box = fixerBoxes["F1"];

【讨论】:

  • 感谢您添加注册名的详细信息!这可能会解决我遇到的第二个问题:)
猜你喜欢
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多