威尼斯人线上娱乐

经过信托实现多窗口间的传值,使用委托完结窗体之间的传值

8 4月 , 2019  

在动用WPF开发的时候就在所难免会赶上必要多个窗口间开始展览传值操作,当然多窗口间传值的方法有广大种,本文介绍的是应用委托落成多窗口间的传值。

简介

  本文将完全叙述本身利用VisualTreeHelper达成题述功效的整套历程,想平昔看函数达成的恋人能够跳到函数达成部分。 
  或然直接在GitHub上下载源码。 
   
  在WPF中大家平日会遇见那种处境:当我们品尝着去搜寻窗体也许页面中有个别控件的子控件大概父控件的时候,大家不得不寻找到它的首先级的逻辑子级对象只怕父级对象。当大家想更深切的时候,就从不章程了。 
  甚至在大家自定义的DataTemplate中的控件,大家都无法对其访问。比如在ListView中自定义的控件,大家就不能获得钦点地方的控件了。相关例子能够瞻仰作者的博文: WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加运载飞机制初探 。 
  本文将追究消除方案。

威尼斯人线上娱乐 ,下边小编达成一个最简易的页面传值效率,相信初学者能一看就通晓。

看看新浪有篇小说聊到“使用C#编制程序的办法开创DataTemplate数据模板”(原稿地址),
博主的做法是开创3个FrameworkElementFactory对象,设置好后将其安装为DataTemplate对象的VisualTree属
性。笔者以为此办法有待商榷,盖因查阅MSDN,发现FrameworkElementFactory类的介绍页面上有1段备注:
(http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelementfactory.aspx)

在上代码在此之前呢,先不难介绍一下什么是C#中的委托(假若只想掌握怎么传值可以略过那某些)在互连网上有很多对此信托的介绍和教学,经过本人的上学和小结加上了几许自笔者本身的精通,作者认为委托是一体系似于C语言的指针,但是它指向的是方式而不是变量。假如把信托看作八个变量,那么那么些变量里存着的正是您目的措施的地址,调用委托相当于调用你的靶子措施。(个人知道欢迎指正调换)

VisualTreeHelper

  微软在VisualTreeHelper类中,提供了有个别实用工具方法,用于实践涉及可视化树中的节点的正规职责,VisualTreeHelper
类中的一些措施能够承受代表任意一种可视对象类型的 DependencyObject
值。 
  那里我们将要用到四个办法分别是:VisualTreeHelper.GetChild()和VisualTreeHelper.GetParent()。

威尼斯人线上娱乐 1点击打开按扭,打开传输值窗体

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

 

使用VisualTreeHelper

威尼斯人线上娱乐 2威尼斯人线上娱乐 3View Code


经过信托实现多窗口间的传值,使用委托完结窗体之间的传值。以下正文:

效仿场景搭建

  新建一个WPF工程,命名字为VisualTreeHelperDemo。 
  借使我们有如下如所示的一个主窗体,窗体的始末容器为二个name=”TopGrid”的Grid控件,它富含了上下七个子级Grid,每种子级Grid中分头蕴涵了1个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代码并且选用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,结果如下图: 

 
  威尼斯人线上娱乐 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某1项,输入框内容会实时更新,也足以实时修改名字和别称。首先使用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二,效果如下: 
威尼斯人线上娱乐 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’将显得在接收值窗体的Text博克斯上

下边将Text博克斯、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定义了贰个DataTemplate,并将之实例化,达成了ListBox的数据绑定操作:

威尼斯人线上娱乐 15

威尼斯人线上娱乐 16😉

MainWindow.xaml.cs:

第二个窗口Window1代码:

此地首要为大家显示了三种传值方式:

威尼斯人线上娱乐 17

Window1.xaml

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

参照出处:

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

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

效果图:

再来看多少个传值的措施,有如下三种办法,其中首要讲讲事件订阅传值的款式。

威尼斯人线上娱乐 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 -> 在子窗口中的TextBox中输入值, 点击OK后关闭
-> 主窗口上的TextBox获取子窗口中的值。

威尼斯人线上娱乐 21

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

未来就已经实现了窗口间传值的操作了。接下来小编会不难介绍一下上述代码的落到实处格局和部分和谐的精通,假使不感兴趣恐怕已经会利用委托开始展览多窗口间的传值了,前面包车型客车一对能够略过。 

威尼斯人线上娱乐 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😉

此情势即为委托的靶子措施,此方法再次回到值为空,也能够安装其再次回到值,当使用委托时也会收取目的措施的重临值。再有就是此措施接收七个参数,二个是字符串1个是TextBox,第2个参数倒是没什么实际意义,只是为着表明那里传递的变量能够四个,也足以是其他object类型。

2.
 在主窗口中的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代理的一个实例对象并且被定义成event类型,所以在此外类里就能够订阅这么些事件了。

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

 

delegate是声称委托的关键字,那里的重回值为空,若目的措施是有重临值的,在那里将重返值写成同种类型即可,接收的三个变量类型也要和指标措施一致。

参考出处:

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

getTextHandler(Window1TextBox.Text, Window1TextBox);

 

 

编著至尾,委托的利用还有许多,例如:事件订阅,匿名格局,多播委托等等,本文介绍的则是寄托的骨干使用格局,其余的用法仍在读书个中,欢迎指正交换。

 

2018.八.30晚上三点差五分


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图