在运用WPF开发的时候就不免会赶上必要五个窗口间展开传值操作,当然多窗口间传值的方法有举不胜举种,本文介绍的是利用委托完毕多窗口间的传值。

简介

  本文将完全叙述本身使用VisualTreeHelper完结题述功效的任何进度,想一直看函数完毕的对象能够跳到函数实现部分。 
  或然直接在透过委托完成多窗口间的传值,事件订阅达成传值。GitHub上下载源码。 
   
  在WPF中大家日常会遇上这种景色:当大家尝试着去追寻窗体也许页面中某些控件的子控件恐怕父控件的时候,大家只好寻找到它的率先级的逻辑子级对象可能父级对象。当大家想更深刻的时候,就从未艺术了。 
  甚至在我们自定义的DataTemplate中的控件,大家都不可能对其访问。比如在ListView中自定义的控件,大家就不能获得钦赐地方的控件了。相关例子能够瞻仰小编的博文: WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加运载飞机制初探 。 
  本文将探究化解方案。

上面作者达成3个最不难易行的页面传值功用,相信初大家能1看就通晓。

探望博客园有篇文章聊到“使用C#编制程序的办法创立DataTemplate数据模板”(初稿地址),
博主的做法是创办二个FrameworkElementFactory对象,设置好后将其设置为DataTemplate对象的VisualTree属
性。作者认为此方法有待商谈,盖因查阅MSDN,发现FrameworkElementFactory类的牵线页面上有一段备注:
(http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelementfactory.aspx)

在上代码在此以前呢,先容易介绍一下怎样是C#中的委托(假若只想精晓哪些传值可以略过那部分)在网络上有很多对于信托的牵线和教师,经过自家的就学和计算加上了1些我要好的驾驭,作者觉着委托是一种恍若于C语言的指针,可是它指向的是办法而不是变量。若是把信托看作一个变量,那么那个变量里存着的便是你指标措施的地方,调用委托也便是调用你的目的措施。(个人驾驭欢迎指正交换)

VisualTreeHelper

  微软在VisualTreeHelper类中,提供了1部分实用工具方法,用于实施涉及可视化树中的节点的例行任务,VisualTreeHelper
类中的1些方法尚可代表任意一种可视对象类型的 DependencyObject
值。 
  那里大家将要用到多少个章程分别是:VisualTreeHelper.GetChild()和VisualTreeHelper.GetParent()。

金沙注册送58 1点击打开按扭,打开传输值窗体

  备注:通过此类以编程格局创立模板那种格局已被推翻,这么些模板是
FrameworkTemplate(如 ControlTemplate 或
DataTemplate)的子类;使用此类创造模板时,并非全部模板作用都可用。以编制程序格局创造模板的推荐介绍方式是:使用
XamlReader 类的 Load 方法从字符串或内部存款和储蓄器流中加载 XAML。

 

使用VisualTreeHelper

金沙注册送58 2金沙注册送58 3View Code


以下正文:

依傍场景搭建

  新建三个WPF工程,命名称为VisualTreeHelper德姆o。 
  要是大家有如下如所示的三个主窗体,窗体的内容容器为二个name=”TopGrid”的Grid控件,它含有了上下八个子级Grid,各种子级Grid中分头包括了贰个Button。 
  金沙注册送58 4 
  MainWindow.xaml代码如下:  

 1 <Window x:Class="VisualTreeHelper.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         Title="MainWindow" Height="350" Width="525">
 5     <Grid Name="TopGrid">
 6         <Grid.RowDefinitions>
 7             <RowDefinition></RowDefinition>
 8             <RowDefinition></RowDefinition>
 9         </Grid.RowDefinitions>
10         <Grid >
11             <Button Content="Button1" Name="btn_One" VerticalAlignment="Center" HorizontalAlignment="Center">
12             </Button>
13         </Grid>
14         <Grid  Grid.Row="1">
15             <Button Content="Button2" Name="btn_Two" VerticalAlignment="Center" HorizontalAlignment="Center">
16             </Button>
17         </Grid>
18     </Grid>
19 </Window>

金沙注册送58 5😉

  由此,正确的做法如同是编制程序成立一段XAML代码并且选用XamlReader类的Load方法将其组织成为实例对象。上边代码展现了那1做法(为了演示,数据绑定操作全部由C#代码而不是xaml达成):

兑现窗口间的并行传值,先创制五个窗口,先上代码主窗口代码:

遍历寻找子级对象

  以往大家来寻觅TopGrid全体Button子级对象,并出口它们的称呼。 
  打开MainWindow.xaml.cs文件,添加寻找子级对象的代码如下:

 1 /// <summary>
 2 /// 利用visualtreehelper寻找对象的子级对象
 3 /// </summary>
 4 /// <typeparam name="T"></typeparam>
 5 /// <param name="obj"></param>
 6 /// <returns></returns>
 7 List<T> FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
 8 {
 9     try
10     {
11         List<T> TList = new List<T> { };
12         for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
13         {
14             DependencyObject child = VisualTreeHelper.GetChild(obj, i);
15             if (child != null && child is T)
16             {
17                 TList.Add((T)child);
18                 List<T> childOfChildren = FindVisualChild<T>(child);
19                 if (childOfChildren != null)
20                 {
21                     TList.AddRange(childOfChildren);
22                 }
23             }
24             else
25             {
26                 List<T> childOfChildren = FindVisualChild<T>(child);
27                 if (childOfChildren != null)
28                 {
29                     TList.AddRange(childOfChildren);
30                 }
31             }
32         }
33         return TList;
34     }
35     catch (Exception ee)
36     {
37         MessageBox.Show(ee.Message);
38         return null;
39     }
40 }

 在btn_One_Click事件之中书写代码如下:

 

 1 /// <summary>
 2 /// 窗体加载事件
 3 /// </summary>
 4 /// <param name="sender"></param>
 5 /// <param name="e"></param>
 6 private void btn_One_Click(object sender, RoutedEventArgs e)
 7 {
 8     string btnName = "";
 9     List<Button> btnList = FindVisualChild<Button>(TopGrid);
10     foreach (Button item in btnList)
11     {
12         btnName += string.IsNullOrEmpty(btnName) ? item.Name.ToString() : "," + item.Name.ToString();
13     }
14     Show(string.Format(TopGrid.Name.ToString()+"共有{0}个Button,名称分别为{1}", btnList.Count, btnName));
15 }

 

运行程序,点击Button1,结果如下图: 

 
  金沙注册送58 6 
   
  结果申明遍历成功。 

 

 1 public partial class Form1 : Form
 2     {
 3         public Form1()
 4         {
 5             InitializeComponent();
 6         }
 7 
 8         public void getValue(string strV)
 9         {
10             this.textBox1.Text = strV;
11         }
12 
13         private void button1_Click(object sender, EventArgs e)
14         {
15             Form2 frm = new Form2();
16             //frm.fatherform = this;//将当前窗体赋给fatherform
17             //frm.getTextHandler += new Form2.GetTextHandler(getValue);//给事件赋值(注意:GetText方法的参数必须与GetTextHandler委托的参数一样,方可委托)
18             frm.getTextHandler = getValue;//将方法赋给委托对象
19             frm.ShowDialog();
20         }
21     }

  上面代码完成一个小程序,该程序能够输入名字和别名,将之投入到ListBox列表中,若是选中ListBox某壹项,输入框内容会实时更新,也能够实时修改名字和别名。首先使用XAML描述出程序界面:

MainWindow.xaml

遍历寻找父级对象

  现在大家来遍历Button二的父级对象,获得其独具父级对象的新闻,并且展现。 
  打开MainWindow.xaml.cs文件,添加寻找父级对象的代码如下:

 1 /// <summary>
 2 /// 利用VisualTreeHelper寻找指定依赖对象的父级对象
 3 /// </summary>
 4 /// <typeparam name="T"></typeparam>
 5 /// <param name="obj"></param>
 6 /// <returns></returns>
 7 public static List<T> FindVisualParent<T>(DependencyObject obj) where T : DependencyObject
 8 {
 9     try
10     {
11         List<T> TList = new List<T> { };
12         DependencyObject parent = VisualTreeHelper.GetParent(obj);
13         if (parent != null && parent is T)
14         {
15             TList.Add((T)parent);
16             List<T> parentOfParent = FindVisualParent<T>(parent);
17             if (parentOfParent !=null)
18             {
19                 TList.AddRange(parentOfParent);
20             }
21         }
22         else if ( parent != null )
23         {
24              List<T> parentOfParent = FindVisualParent<T>(parent);
25              if (parentOfParent != null)
26              {
27                  TList.AddRange(parentOfParent);
28              }
29         }
30         return TList;
31     }
32     catch (Exception ee)
33     {
34         MessageBox.Show(ee.Message);
35         return null;
36     }
37 }

在btn_Two_Click中添加代码如下:

 

 1 /// <summary>
 2 /// 遍历Button2父级对象信息
 3 /// </summary>
 4 /// <param name="sender"></param>
 5 /// <param name="e"></param>
 6 private void btn_Two_Click(object sender, RoutedEventArgs e)
 7 {
 8     string parentName = "";
 9     List<Grid> gridList = FindVisualParent<Grid>(btn_Two);
10     foreach (Grid item in gridList)
11     {
12         parentName += string.IsNullOrEmpty(parentName) ? item.Name.ToString() : "," + item.Name.ToString();
13     }
14     MessageBox.Show(string.Format(btn_Two.Name.ToString() + "共有{0}个逻辑父级,名称分别为{1}", gridList.Count, parentName));
15 }

 

运作程序,点击Button二,效果如下: 
金沙注册送58 7 
  结果声明遍历成功。

金沙注册送58 8😉

MainWindow.xaml:

<Grid>
  <TextBox Name="MainWindowTextBox" HorizontalAlignment="Left" Height="23" Margin="10,61,0,0" TextWrapping="Wrap" Text="空" VerticalAlignment="Top" Width="297"/>
  <Button Content="打开新窗口" HorizontalAlignment="Left" Margin="10,130,0,0" VerticalAlignment="Top" Width="297" Click="ButtonBase_OnClick"/>
</Grid>

总结

  通过上述的艺术我们就足以随心所欲地获取大家想要的控件对象,并对其进行操作,包涵自定义的DataTemplate中的控件都得以获取。

 

 

金沙注册送58 9

 MainWindow.xaml.cs

金沙注册送58 10输入值后点击传输按扭,’value’将显得在接收值窗体的TextBox上

下边将TextBox、ListBox的数据源全体绑定到大家友好的数据结构上,先定义1个NickName类,达成INotifyPropertyChanged接口:

 1 public void GetValue(string value1, TextBox value2)
 2   {
 3     MainWindowTextBox.Text = value1;
 4   }
 5 
 6 private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
 7   {
 8     Window1 newWindow1 = new Window1();
 9     newWindow1.getTextHandler = GetValue;          //将方法赋给委托对象
10     newWindow1.ShowDialog();
11 
12   }

金沙注册送58 11金沙注册送58 12View Code

MainWindow.xaml.cs:

 

金沙注册送58 13😉

金沙注册送58 14

功用图如下:

 1 public partial class Form2 : Form
 2     {
 3         public Form2()
 4         {
 5             InitializeComponent();
 6         }
 7         //public Form1 fatherform;
 8 
 9         public delegate void GetTextHandler(string text);//声明委托
10        // public event GetTextHandler getTextHandler = null;//定义委托事件
11        public  GetTextHandler getTextHandler;//委托对象
12         private void button1_Click(object sender, EventArgs e)
13         {
14             //if (fatherform != null)
15             //{
16             //    fatherform.getValue(this.textBox1.Text.Trim());
17             //    this.Close();
18             //}
19             if (getTextHandler != null)
20             {
21                 getTextHandler(this.textBox1.Text.Trim());
22                 this.Close();
23             }
24         }
25     }

上面代码在内存中使用XAML定义了三个DataTemplate,并将之实例化,完毕了ListBox的数目绑定操作:

金沙注册送58 15

金沙注册送58 16😉

MainWindow.xaml.cs:

其次个窗口Window一代码:

那里首要为我们显示了二种传值形式:

金沙注册送58 17

Window1.xaml

壹、将Form1窗体传给fatherform对象,随后大家就能够在Form第22中学操作Form一了。
二、使用委托,将getValue方法赋给事件或委托对象getTextHandler,那么达成getValue操作就不要本人去做了因为已经济委员会托给getTextHandler,间接调用getTextHandler即可

经过上述代码,已经打响使用C#代码创立了DataTemplate数据模板,并实现了那一个小程序:

<Grid>
    <TextBox Name="Window1TextBox" HorizontalAlignment="Left" Height="23" Margin="84,73,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="120"/>
    <Button Content="传值" HorizontalAlignment="Left" Margin="84,125,0,0" VerticalAlignment="Top" Width="120" Click="ButtonBase_OnClick"/>
</Grid>

 

金沙注册送58 18

 Window1.xaml.cs

参照出处:

由于刚(Yu-Gang)开头读书WPF,代码中难免有不当之处,恳请牛人指正。

1 public delegate void GetTextHandler(string value1, TextBox value2);  //声明委托
2 public GetTextHandler getTextHandler;                                //委托对象
3 
4 private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
5   {
6     getTextHandler(Window1TextBox.Text, Window1TextBox);
7   }

===================================================================

效果图:

再来看多少个传值的不二等秘书籍,有如下两种办法,在那之中第贰讲讲事件订阅传值的情势。

金沙注册送58 19

  1. 证明个全局变量,就是App.xaml里面注明;在具备窗体里面都足以引用
    Application.Current.Properties[“ArgumentName”]金沙注册送58,;

  2. 第2个正是 在目的窗体下边公开个 属性,直接赋值;

  3. 末尾正是在Uri里面传参数 NavigationService.Navigate(window
    object,argument value)

  4. 动用事件响应,传递值。 

落到实处际效果益当运转程序后,点击打开新窗口按钮后,会打开Window壹窗口,在Window壹窗口的Textbox中输入内容,点击传值,你所输入的内容就会传出主窗口,通过委托的风浪将主窗口中的Textbox控件的剧情改动为你传过去的值。效果如下:

 

金沙注册送58 20

比方:点击主窗口MainWindow 上的1个OpenSubWindow按钮 ->
打开子窗口SubWindow -> 在子窗口中的TextBox中输入值, 点击OK后关闭
-> 主窗口上的TextBox获取子窗口中的值。

金沙注册送58 21

  1. 在子窗口中定义四个轩然大波PassValues伊芙nt。 当点击 OK
    按钮时,触发事件,并传递数值。( PassValues伊夫ntArgs
    是伊夫ntArgs类,须要同时定义好) 

后天就早已完毕了窗口间传值的操作了。接下来笔者会简单介绍一下以上代码的完毕形式和一部分投机的掌握,如果不感兴趣或许曾经会采用委托开展多窗口间的传值了,前边的一对能够略过。 

金沙注册送58 22😉

前台代码在此就先不介绍了哈,在MainWindow.xaml.cs文件中

    public partial class SubWindow : Window
    {
        public delegate void PassValuesHandler(object sender, PassValuesEventArgs e);

        public event PassValuesHandler PassValuesEvent; 

        public SubWindow()
        {
            InitializeComponent();
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            string value1 = tbValue1.Text;   // Text Property return value is string type .
            int value2;
            Int32.TryParse(tbValue2.Text, out value2);

            PassValuesEventArgs args = new PassValuesEventArgs(value1, value2);
            PassValuesEvent(this, args);

            this.Close();
        }
    }
public void GetValue(string value1, TextBox value2)

金沙注册送58 23😉

此情势即为委托的指标措施,此方法再次回到值为空,也足以设置其重返值,当使用委托时也会接受指标措施的再次回到值。再有正是此措施接收五个参数,2个是字符串1个是Text博克斯,第3个参数倒是没什么实际意义,只是为着印证那里传递的变量能够八个,也得以是其余object类型。

二.
 在主窗口中的OpenSubWindow按钮点击的不二等秘书籍中,订阅了PassValues伊芙nt事件。当事件触发时,获取传递的参数的值。

 

金沙注册送58 24😉

newWindow1.getTextHandler = GetValue;          //将方法赋给委托对象
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnOpenSubWindow_Click(object sender, RoutedEventArgs e)
        {
            SubWindow subWindow = new SubWindow(); 

            // 订阅事件
            subWindow.PassValuesEvent += new SubWindow.PassValuesHandler(ReceiveValues);

            subWindow.Show(); 
        }

        private void ReceiveValues(object sender, PassValuesEventArgs e)
        {
            this.tbValue1.Text = e.Value1;
            this.tbValue2.Text = e.Value2.ToString(); 
        }
    }

将艺术赋给委托对象,可以领略为把她们多个绑定在联合的getTextHandler这一个委托对应的靶子措施正是GetValue。

金沙注册送58 25😉

在Windo1.xaml.cs中:

 重要表明:子窗口的PassValues伊芙nt事件,是从PassValuesHandler代理的七个实例对象并且被定义成event类型,所以在别的类里就能够订阅那么些事件了。

public delegate void GetTextHandler(string value1, TextBox value2);  //声明委托
public GetTextHandler getTextHandler;                                //委托对象

 

delegate是声称委托的显要字,那里的再次来到值为空,若指标措施是有重回值的,在此间将再次回到值写成同类别型即可,接收的八个变量类型也要和目的措施同样。

参照出处:

接下去正是概念委托对象,大写的GetTextHandler是信托,而小写的getTextHandler是指标,在运用该信托时候利用的也是小写的getTextHandler使用方法:

getTextHandler(Window1TextBox.Text, Window1TextBox);

 

 

创作至尾,委托的利用还有不少,例如:事件订阅,匿名情势,多播委托等等,本文介绍的则是委托的主旨使用方法,其余的用法仍在求学当中,欢迎指正调换。

 

201八.八.30晚上③点差5分

相关文章

网站地图xml地图