在程序代码中选拔DataTemplate的另类方法,通过委托达成多窗口间的传值

在行使WPF开发的时候就难免会碰着要求七个窗口间展开传值操作,当然多窗口间传值的措施有许各种,本文介绍的是选取委托达成多窗口间的传值。

简介

  本文将总体叙述本身动用VisualTreeHelper实现题述作用的上上下下进度,想一直看函数完毕的情人能够跳到函数完成部分。 
  只怕直接在GitHub上下载源码。 
   
  在WPF中大家平常会境遇那种景况:当我们品尝着去寻觅窗体也许页面中有些控件的子控件大概父控件的时候,大家只好寻找到它的率先级的逻辑子级对象恐怕父级对象。当大家想更透彻的时候,就没有办法了。 
  甚至在大家自定义的DataTemplate中的控件,大家都无法对其访问。比如在ListView中自定义的控件,大家就不可能获得内定位置的控件了。相关例子能够瞻仰作者的博文: WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加运载飞机制初探 在程序代码中选拔DataTemplate的另类方法,通过委托达成多窗口间的传值。。 
  本文将研讨化解方案。

上边作者实现二个最简单易行的页面传值功用,相信初专家能壹看就明白。

总的来看天涯论坛有篇作品聊起“使用C#编制程序的艺术创设DataTemplate数据模板”(原来的小说地址亚洲必赢官网,),
博主的做法是创制一个FrameworkElementFactory对象,设置好后将其设置为DataTemplate对象的VisualTree属
性。小编认为此方法有待商谈,盖因查阅MSDN,发现FrameworkElementFactory类的牵线页面上有1段备注:
(http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelementfactory.aspx)

在上代码从前呢,先简单介绍一下怎么样是C#中的委托(假诺只想询问哪些传值能够略过那部分)在网络上有很多对于信托的牵线和助教,经过自家的求学和计算加上了有些自个儿要好的精通,小编觉着委托是壹种恍若于C语言的指针,不过它指向的是措施而不是变量。若是把信托看作一个变量,那么那个变量里存着的正是你指标措施的地方,调用委托也正是调用你的对象措施。(个人领会欢迎指正交换)

VisualTreeHelper

  微软在VisualTreeHelper类中,提供了1些实用工具方法,用于实施涉及可视化树中的节点的健康职分,VisualTreeHelper
类中的一些主意尚可代表任意一种可视对象类型的 DependencyObject
值。 
  这里大家就要用到三个主意分别是:VisualTreeHelper.GetChild()和VisualTreeHelper.GetParent()。

亚洲必赢官网 1点击打开按扭,打开传输值窗体

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

 

使用VisualTreeHelper

亚洲必赢官网 2亚洲必赢官网 3View Code


以下正文:

模仿场景搭建

  新建1个WPF工程,命名称叫VisualTreeHelper德姆o。 
  即使大家有如下如所示的2个主窗体,窗体的始末容器为三个name=”TopGrid”的Grid控件,它包罗了上下七个子级Grid,各个子级Grid中分头包括了多少个Button。 
  亚洲必赢官网 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>

亚洲必赢官网 5😉

  由此,正确的做法就好像是编程创造壹段XAML代码并且采纳Xaml里德r类的Load方法将其结构成为实例对象。上面代码突显了那一做法(为了演示,数据绑定操作全部由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 }

 

运作程序,点击Button一,结果如下图: 

 
  亚洲必赢官网 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 }

 

运作程序,点击Button2,效果如下: 
亚洲必赢官网 7 
  结果申明遍历成功。

亚洲必赢官网 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中的控件都得以收获。

 

 

亚洲必赢官网 9

 MainWindow.xaml.cs

亚洲必赢官网 10输入值后点击传输按扭,’value’将显得在接收值窗体的TextBox上

下面将TextBox、ListBox的数据源全体绑定到大家温馨的数据结构上,先定义三个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   }

亚洲必赢官网 11亚洲必赢官网 12View Code

MainWindow.xaml.cs:

 

亚洲必赢官网 13😉

亚洲必赢官网 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定义了3个DataTemplate,并将之实例化,达成了ListBox的多寡绑定操作:

亚洲必赢官网 15

亚洲必赢官网 16😉

MainWindow.xaml.cs:

第二个窗口Window1代码:

那边根本为我们突显了二种传值形式:

亚洲必赢官网 17

Window1.xaml

一、将Form一窗体传给fatherform对象,随后大家就足以在Form第22中学操作Form1了。
二、使用委托,将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>

 

亚洲必赢官网 18

 Window1.xaml.cs

参考出处:

鉴于刚同志初始读书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   }

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

效果图:

再来看多少个传值的诀要,有如下三种艺术,当中首要讲讲事件订阅传值的款式。

亚洲必赢官网 19

  1. 声称个全局变量,正是App.xaml里面证明;在富有窗体里面都得以引用
    Application.Current.Properties[“ArgumentName”];

  2. 其次个正是 在指标窗体下边公开个 属性,直接赋值;

  3. 最后就是在Uri里面传参数 NavigationService.Navigate(window
    object,argument value)

  4. 选拔事件响应,传递值。 

金玉锦绣效益当运营程序后,点击打开新窗口按钮后,会打开Window一窗口,在Window一窗口的Textbox中输入内容,点击传值,你所输入的始末就会传来主窗口,通过信托的事件将主窗口中的Textbox控件的情节变更为你传过去的值。效果如下:

 

亚洲必赢官网 20

比喻:点击主窗口MainWindow 上的三个OpenSubWindow按钮 ->
打开子窗口SubWindow -> 在子窗口中的Text博克斯中输入值, 点击OK后关门
-> 主窗口上的TextBox获取子窗口中的值。

亚洲必赢官网 21

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

后天就早已落到实处了窗口间传值的操作了。接下来笔者会简单介绍一下以上代码的兑现格局和部分协调的了然,假如不感兴趣大概已经会利用委托举行多窗口间的传值了,后边的壹些能够略过。 

亚洲必赢官网 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)

亚洲必赢官网 23😉

此办法即为委托的指标措施,此措施再次来到值为空,也足以安装其再次来到值,当使用委托时也会吸收接纳指标措施的重回值。再有正是此方法接收三个参数,八个是字符串一个是TextBox,第叁个参数倒是没什么实际意义,只是为着注脚那里传递的变量能够多少个,也得以是其余object类型。

二.
 在主窗口中的OpenSubWindow按钮点击的章程中,订阅了PassValues伊夫nt事件。当事件触发时,获取传递的参数的值。

 

亚洲必赢官网 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。

亚洲必赢官网 25😉

在Windo1.xaml.cs中:

 首要表达:子窗口的PassValues伊夫nt事件,是从PassValuesHandler代理的3个实例对象并且被定义成event类型,所以在其余类里就能够订阅那几个事件了。

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

 

delegate是宣称委托的第一字,那里的重临值为空,若目的措施是有再次回到值的,在那边将再次来到值写成同类别型即可,接收的七个变量类型也要和对象措施同样。

参照出处:

接下去便是概念委托对象,大写的GetTextHandler是寄托,而小写的getTextHandler是目的,在采用该信托时候利用的也是小写的getTextHandler使用办法:

getTextHandler(Window1TextBox.Text, Window1TextBox);

 

 

写作至尾,委托的运用还有很多,例如:事件订阅,匿名形式,多播委托等等,本文介绍的则是寄托的主干采取格局,别的的用法仍在就学其中,欢迎指正调换。

 

201八.8.30下午3点差四分

网站地图xml地图