【问题标题】:Can I get access from code behind (of a ResourceDictionary) to a named control?我可以从(ResourceDictionary)后面的代码访问命名控件吗?
【发布时间】:2017-06-06 10:16:04
【问题描述】:

是否可以从 (ResourceDictionary) 后面的代码访问命名控件?

例如对我来说,有必要创建很多文件夹选择对话框。对于必须选择的每个文件夹,一个对话框可能包含几行。 每行包括:标签(名称)、文本框(选择的路径)和一个按钮(打开 FileBrowserDialog)。

所以现在我想在 FileBrowserDialog 完成后访问 TextBox。但我无法从 CodeBehind 访问“SelectedFolderTextBox”。

有没有更好的方法来实现我想做的事情?

XAML

<ResourceDictionary ...>
    ...

    <StackPanel x:Key="FolderSearchPanel"
                x:Shared="False">
        <Label Content="Foldername"/>
        <TextBox x:Name="SelectedFolderTextBox" 
                 Text="C:\Folder\Path\"/>
        <Button Content="..."
                Click="Button_Click"/>
    </StackPanel>
</ResourceDictionary>

代码隐藏

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Initialize and show
    var dialog = new System.Windows.Forms.FolderBrowserDialog();
    System.Windows.Forms.DialogResult result = dialog.ShowDialog();

    // Process result
    if (result == System.Windows.Forms.DialogResult.OK)
    {
        string selectedPath = dialog.SelectedPath;

        SelectedFolderTextBox.Text = selectedPath;  // THIS DOES NOT WORK
                                                    // since I don't have access to it
                                                    // but describes best, what I want to do
    }
}

【问题讨论】:

    标签: c# wpf controls resourcedictionary xname


    【解决方案1】:

    您应该能够将sender 参数转换为Button,然后将ButtonParent 属性转换为StackPanel,并在@ 的Children 集合中找到控件987654327@。像这样的:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // Initialize and show
        var dialog = new System.Windows.Forms.FolderBrowserDialog();
        System.Windows.Forms.DialogResult result = dialog.ShowDialog();
    
        // Process result
        if (result == System.Windows.Forms.DialogResult.OK)
        {
            string selectedPath = dialog.SelectedPath;
    
            Button clickedButton = sender as Button;
            StackPanel sp = clickedButton.Parent as StackPanel;
            if (sp != null)
            {
                TextBox SelectedFolderTextBox = sp.Children.OfType<TextBox>().FirstOrDefault(x => x.Name == "SelectedFolderTextBox");
                if (SelectedFolderTextBox != null)
                    SelectedFolderTextBox.Text = selectedPath;
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      当你有一组重复的控件和一些相关的功能时,创建一个可重用的控件是有意义的:

      通过项目“添加项目”对话框添加用户控件并使用此 xaml 和代码:

      <UserControl x:Class="WpfDemos.FolderPicker"
                   x:Name="folderPicker"
                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                   xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                   mc:Ignorable="d" 
                   d:DesignHeight="75" d:DesignWidth="300">
          <StackPanel>
              <Label Content="{Binding Path=Title, ElementName=folderPicker}"/>
              <TextBox x:Name="SelectedFolderTextBox" 
                       Text="{Binding Path=FullPath, ElementName=folderPicker,
                                      UpdateSourceTrigger=PropertyChanged}"/>
              <Button Content="..." Click="PickClick"/>
          </StackPanel>
      </UserControl>
      
      public partial class FolderPicker : UserControl
      {
          public FolderPicker()
          {
              InitializeComponent();
          }
      
          public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
              "Title", typeof (string), typeof (FolderPicker), new PropertyMetadata("Folder"));
      
          public string Title
          {
              get { return (string) GetValue(TitleProperty); }
              set { SetValue(TitleProperty, value); }
          }
      
          public static readonly DependencyProperty FullPathProperty = DependencyProperty.Register(
              "FullPath", typeof (string), typeof (FolderPicker), new FrameworkPropertyMetadata(@"C:\", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
      
          public string FullPath
          {
              get { return (string) GetValue(FullPathProperty); }
              set { SetValue(FullPathProperty, value); }
          }
      
          private void PickClick(object sender, RoutedEventArgs e)
          {
              using (var dialog = new System.Windows.Forms.FolderBrowserDialog())
              {
                  if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                      FullPath = dialog.SelectedPath;
              }
          }
      }
      

      TextBox 可以从代码隐藏中访问。依赖属性TitleFullPath 允许为不同的用途自定义控件并创建与视图模型的绑定(这对于声明为资源的控件组是无法做到的)。示例

      查看模型:

      public class MyViewModel
      {
          public string Src { get; set; }
          public string Target { get; set; }
      }
      

      查看:

      public MyWindow()
      {
          InitializeComponent();
          this.DataContext = new MyViewModel { Src = "C:", Target = "D:" }
      }
      
      <StackPanel>
          <wpfDemos:FolderPicker Title="Source"      FullPath="{Binding Path=Src}"   />
          <wpfDemos:FolderPicker Title="Destination" FullPath="{Binding Path=Target}"/>
      </StackPanel>
      

      【讨论】:

      • 谢谢,您回答了我遇到的下一个问题!所以 UserControl 是我接下来需要创建的 :) 所以 ResourceDictionary 只是为了“愚蠢”好看的东西......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多