views:

226

answers:

1

I have been using this website to learn a lot about C# for a while, but this is my first time posting a question. I look forward to hearing back from some of the seasoned C# veterans!

I have been working on a C# 4.0 WPF project and need to figure out how to databind a boolean value. I have a reference to my Application.Current object in a window. My "App" object contains a boolean field called "Downloaded" that is true if the user has downloaded information from a web service. I need to databind a textbox's IsEnabled field to this Downloaded value. Any tips? Here is what I have come up with so far. (Any useful links to better learn WPF XAML are greatly appreciated!)

C# Code:

class MainWindow : Window
{
... 
private App MyApp = App.Current as App; 
...
}

XAML:

<TextBox ... IsEnabled="{Binding Source=MyApp, Path=Downloaded}" />

James

+4  A: 

WPF can't resolve that Source. If you're specifying a Source in XAML, it will typically be a resource elsewhere in the XAML (e.g. an ObjectDataProvider). MyApp is actually a path from your Window object, not a source in itself.

What you probably want is a multipart path:

{Binding Path=MyApp.Downloaded}

However, you'll still have a few problems with this:

  1. MyApp is a private field. WPF allows binding only to properties (and they should normally be public). So change MyApp to be a public property.
  2. The binding shown is relative to the local DataContext, which will not by default be the Window. So you either need to set the DataContext to the Window (generally poor style), place the MyApp property on a view model class and set the Window.DataContext to be that view model (generally the recommended style) or use a RelativeSource or ElementName on the binding to make it resolve the path against the Window object instead of the DataContext.

Note also you must implement INotifyPropertyChanged on your App class, and raise PropertyChanged for the Downloaded property.

itowlson
or implement Downloaded as a DependancyProperty
Muad'Dib
Thank you so much for the quick response! I changed my code to the following:<code>class MainWindow : Window{public App MyApp{get{return App.Current as App;}}}</code>and the XAML to:<code>IsEnabled="{Binding Path=MyApp.Downloaded, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"</code>and that worked perfectly. Please let me know if this is not the "right way" to do this in WPF. I like to learn things correctly, not just make them work.
jdangelo
And I guess I need to look up how to add <code> blocks in Stackoverflow.com!
jdangelo
Yes, that's a reasonable way of doing it, but for the "right way" longer term you should look into the "model-view-viewmodel" (MVVM) pattern. Lots of links on Google and here on SO. But don't get hung up on it right now -- good to be aware of MVVM as a style to move towards but don't feel you have to break working code to adopt it from day one!
itowlson
Thanks much. I will look into it. I am pretty new to WPF and am trying to learn it the right way so I don't have to go back and fix spaghetti.
jdangelo