在C# WPF中从另一个类访问访问控件的属性

5
我在类之间的可见性方面遇到了问题。请帮我解决这个新手问题。
我有两个控件(来自默认 WPF 工具箱的 DatePickers),它们位于不同的窗口中,因此位于不同的类中。我可以轻松地从其本机类中访问这些控件属性,例如 datePicker1.Text,也就是在其本机窗口中,但是当我尝试从另一个窗口中访问 datePicker1.Text 时却无法获得任何结果。
我尝试使用我的代码中窗口的引用将一个 datePicker 的值分配给另一个 datePicker:
string testStr;
...
AnotherWindow aw = new AnotherWindow();
testStr = aw.datePicker2.Text;
datePicker1.Text = testStr;

"而且它不起作用。同时,我尝试通过类的公共属性来完成它,例如:"
public partial class AnotherWindow : Window
{
....

public string dateNearest
    {

        get { return datePicker2.Text; }
        set { datePicker2.Text = value; }
    }
....

然后在另一个窗口中使用它:
string testStr;
...      
AnotherWindow aw = new AnotherWindow();
testStr = aw.dateNearest;

但也没有分配任何值。
请帮我理解这个基本问题。我知道在WPF中还有其他访问值的方式,比如数据绑定,但我想先了解基础知识。

1
好问题。出于好奇,你更熟悉Win Forms吗?无论如何,我希望你的WPF体验是积极的! :) - Russell
我会说我对C#甚至整个面向对象编程都比较新。我有工业自动化过程语言的强大背景。是的,我在WinForms中的第一次尝试就是使用C#。 - rem
3个回答

2

很不幸,WPF的基础是数据绑定。以其他方式进行操作是“逆向操作”,是不好的实践,通常编码和理解上更加复杂。

对于您的问题,如果您有要在视图之间共享的数据(即使只有一个视图),请创建一个视图模型类,其中包含表示数据的属性,并从视图中绑定到这些属性。

在您的代码中,仅管理您的视图模型类,不要触及实际的视图及其可视控件和可视组合。


True,databinding和MVVM是WPF设计的架构模型。然而,我的经验表明,我们需要一种温和的方法来帮助过渡从Windows Forms设计技术到WPF。 - Russell
我的经验是,如果您试图将最糟糕的WinForms设计技术“过渡”到WPF中,您的开发人员最终会持续多年地产生糟糕的设计。甚至可能最终不得不用其他开发人员替换他们以获得体面的WPF代码。另一方面,如果您向他们展示如何使用WPF和MVVM更轻松地完成当前任务,他们就永远不会走错路,从长远来看,情况会好很多。 - Ray Burns
1
我同意两种相互矛盾的观点。最佳实践对于专业程序员来说是必不可少的,但对于学习者来说,“软过渡方法”有时也是至关重要的。即使以肮脏和原始的形式(一些“Hello world”方法)得到一些东西并继续前进而不感到沮丧非常重要。 - rem
@Russell,@Ray:对我来说,“数据绑定”与“依赖注入”或IOC的概念没有重叠,这是面向对象开发的艺术、技巧和科学,以便在对象之间实现必要的引用和交互,从而实现高效和可维护性。对我来说,到处都出现了这些“框架”(Unity、Castle等),以便让您实现MVC或MVVM,或者任何当年流行的设计哲学,这表明WPF和IDE本身的设计存在根本缺陷。在XAML中工作,恕我直言,有点像回到了石器时代 :) - BillW
MVVM不是今年的流行口味,它是WPF设计的基本模型。你可以放弃一切,但如果你不使用MVVM,你就会陷入沼泽。 - Aviad P.

1

我现在正在使用VS 2010 beta 2,在做最简单的WPF编码时经常会崩溃,比如尝试复制你问题中的代码 :) 但是考虑到:

使用这种语法是否可能会“做正确的事情”:

    public string dateNearest 
    { 
        get { return this.datePicker2.Text; } 
        set { this.datePicker2.Text = value; } 
    }

编辑1:好的,我已经复制了你的WPF代码,并且没有崩溃:使用上述语法,我可以在“其他窗口”中获取和设置属性。

编辑2:你的原始代码也可以正常工作 :) 在我第一次阅读它时,它似乎是“正确的”。你在读取属性之前是否设置了该属性?据我所知,DateTimePicker的Text属性在首次创建时默认为空字符串。

编辑3:回应Rem的请求:

  1. 主窗口有一个名为“button1”的按钮,用于测试在第二个名为“WindowAdded”的窗口实例中定义的公共属性DTContent的设置和获取。以下是主窗口代码中该按钮的“Click”事件处理程序:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
      WindowAdded wa = new WindowAdded();    
      wa.DTContent = DateTime.Now.ToString();
      Console.WriteLine("dt = " + wa.DTContent);
    }
    

编辑4:更好的“现实世界”示例:在大多数情况下,您将要创建另一个窗口的实例,并将其保存下来以供重复使用:个人认为:不要仅存在于按钮单击事件的作用域内。因此,请考虑:

在主窗口代码的范围内定义“占位符”,用于添加窗口:private WindowAdded wa;

在您选择最适合创建该窗口实例的事件中:创建实例,并将其分配给您的“占位符”变量:然后根据需要重新使用它。在WinForms中,我经常创建需要重复使用引用的所需辅助窗口,以便在主窗体的加载或显示事件中访问它们上的某些内容。

讨论:当然,如果您的目的是创建“临时”窗口,并且您不需要再次重用对新窗口实例的引用,则在某些函数的作用域中创建它是可以的。

如果您唯一需要访问第二个窗口上的DateTimePicker,则使用上述建议相同的技术,但仅创建并保持对DateTimePicker实例的引用。


不,还是不行。顺便说一下,谢谢分享关于VS 2010 beta 2的经验。 - rem
该解决方案将解决您的问题@rem。窗口1中DatePicker的Text属性仅在窗口1的范围内可见。在窗口类中公开它作为公共属性,将允许从窗口2查看和操作它。 - Russell
感谢讨论和帮助。我设法让它工作了(这一切对我来说还不是很清楚,但我会好好思考)。 - rem
很抱歉要这么说,但是你鼓励在一个如此糟糕的WPF设计中使用rem让我感到非常震惊。WPF的基础是数据绑定,这是rem应该首先学习的。rem所倾向的技术在不好的WinForms时代已经是糟糕的设计,而在WPF中更是非常非常糟糕的设计。与其帮助他实现他的想法,我建议向他展示更好的方法。 - Ray Burns
1
@Ray:请务必向 OP 展示更好的方法!帮助他明白为什么更好。OP和Rem,当你们在这里看到更好的方法演示时,请接受该答案作为你们的被采纳的答案。我的印象是程序员可以自由选择在 C# 与 XAML 中工作的程度。我回答了 OP 的相当具体的问题。 - BillW
显示剩余2条评论

0

正如其他人已经指出的那样,这可能不是正确的方法,但您可以使用:

<object x:FieldModifier="public".../>

将对象设置为公共的。 请参阅msdn获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接