views:

1181

answers:

3

I'm in a mess with visibility between classes. Please, help me with this newbie question.

I have two controls (DatePickers from default WPF toolbox) which are in different windows, so in different classes. I can easily access these controls properties like datePicker1.Text from within its native class, i.e. in its native window, but when I try to reach datePicker1.Text from another window I get nothing.

I try to assign value of one datePicker to another, using reference to the window in my code:

string testStr;
...
AnotherWindow aw = new AnotherWindow();
testStr = aw.datePicker2.Text;
datePicker1.Text = testStr;

and it doesn't work

also I tried to do it through public property of a class, like:

public partial class AnotherWindow : Window
{
....

public string dateNearest
    {

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

and then use it in another window:

string testStr;
...      
AnotherWindow aw = new AnotherWindow();
testStr = aw.dateNearest;

but also no value assigned.

Please, help me to understand this basic issue. I know there are other ways of accessing values in WPF like databinding, but I would like to understand basics first.

+2  A: 

Unfortunately, the basics of WPF are data bindings. Doing it any other way is 'going against the grain', is bad practice, and is generally orders of magnitude more complex to code and to understand.

To your issue at hand, if you have data to share between views (and even if it's only one view), create a view model class which contains properties to represent the data, and bind to the properties from your view(s).

In your code, only manage your view model class, and don't touch the actual view with its visual controls and visual composition.

Aviad P.
True, databinding and MVVM are arch models that WPF was designed for. However my experience has shown we need a soft approach to help transition windows forms design techniques with WPF.
Russell
My experience has been that if you try to "transition" the worst WinForms design techniques into WPF, your developers end up producing bad designs for years on end. You may even end up having to replace them with other developers to get decent WPF code. On the other hand, if you instead show them how they can do their current task much easier using WPF and MVVM they will never go down the wrong path and things will be a lot better for them in the long run.
Ray Burns
I would agree with both contradictory opinions. Best practices are "the must" for professional programmer, but "soft transitional approach" is sometimes vital for learners. It is very important to get something working, even in dirty and raw form (some "Hello world" approach) and then going ahead without frustration.
rem
@Russell, @Ray : for me "databinding" does not overlap with concepts of "dependency injection," or IOC, the art, craft, and science, of OO deveopment so that necessary references and interactions between objects are implemented efficiently, and maintainably. To me the presence of all these "frameworks" (Unity, Castle, and so on) that are popping up everywhere to enable you to implement MVC or MVVM, or whatever flavour of the year design philosophy, suggest a fundamental flaw in the design of WPF and IDE itself. Working in XAML, imho, is a reversion back to the stone-age :)
BillW
MVVM is not flavor of the year, it's the fundamental model WPF was designed for. You can let everything go, but if you don't use MVVM, you're heading into a swamp.
Aviad P.
+1  A: 

Hi, I'm using VS 2010 beta 2 right now which crashes regularly doing the simplest WPF coding, like trying to duplicate your question's code :) : but consider :

Is it possible that using this syntax will "do the right thing" :

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

Edit 1 : Okay, I got a WPF replication of your code that didn't crash : using the above syntax I can both get and set the property in the "other window."

Edit 2 : The code also works using your original code :) Which, seemed to me to be "proper" the first time I read it. Are you setting that property before you read it ? : to my knowledge a DateTimePicker's Text property will be an empty string by default when first created.

Edit 3 : in response to Rem's request :

  1. the main window has a button, 'button1 : which tests setting and getting the Public Property DTContent defined in the instance of the second Window named : 'WindowAdded : here's the 'Click event handler for that button in the main window's code :

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

Edit 4 : a better "real world" example : most cases you are going to want to create that instance of another window, and hold on to it, for re-use: imho : not have it exist only within the scope of a button's Click event. So consider, please :

Somewhere in the scope of the main window's code define a "place-holder" for the window(s) you will add : private WindowAdded wa;

In the event you select as most appropriate for creating the instance of that window : create the instance, and assign to your "place-holder" variable : then re-use it as needed. In WinForms I most often create required secondary windows that I will need to re-use references to the instances of to access something on them in the main form's load or shown events.

Discussion : of course, if your intent is to create "temporary" windows, and you don't need to re-use that reference to the new window's instance again, then creating it in the scope of some function is fine.

And, if the only thing you ever need to access on your second Window is the DateTimePicker, then you use the same technique suggested above, but create and hold to a reference to the instance of the DateTimePicker only.

BillW
No, all the same it doesn't working. BTW, thanks for sharing experience about VS 2010 beta 2
rem
Regarding your Edit 2, please, could you show in code how you access datePicker2.Text in another window?
rem
This solution will solve your issue @rem. The Text property of the DatePicker in window 1 is only visible in the scope of window 1. Exposing it as a public property in the window class will allow it to be viewed and manipulated from window 2.
Russell
@Russell, I'm going to call Window1 the main window, and Window2 the "secondary" window which is created by code in Window1 : in this case, we are depending on the fact that Window1, by virtue of its being the "creator" of Window2, has access to a reference to the instance of Window2, and its public "whatever." My example, showing the new Window being created in a button Click event, is in some ways, a bad example of "real-world code" since the reference to the instance of Window2 will exist only in the scope of the button click event on Window1. I'll have to do something about that ! thanks,
BillW
Thanks for discussion and help. I managed to get it working (all this is not yet clear for me, but I will think it over)
rem
I'm sorry to say this, but I was frankly shocked that you would encourage rem in such a poor WPF design. The fundamentals of WPF are data binding, and that is what rem should learn first. The techniques rem is leaning toward were already poor design back in the bad old WinForms days, and are very very bad design in WPF. Instead of helping him get his idea working, I say show him a better way.
Ray Burns
@Ray : please, by all means, show the OP the better way ! Help him see why it's better. And, OP, Rem, when you see a better way demonstrated here, please, accept that answer as your accepted answer. My impression is that the programmer is free to choose the extent to which he or she works in C# vs. XAML. I responded to the OP's question which was quite specific.
BillW
A: 

As the others already pointed out, this is probably not the way to go, but you can use:

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

To set the object public. See msdn for more info.

Olle