views:

89

answers:

2

In a simple form, I bind to a number of different objects -- some go in listboxes; some in textblocks.

A couple of these objects have collaborating objects upon which the ToString() method calls when doing its work -- typically a formatter of some kind.

When I step through the code I see that when the databinding is being set up,

  1. ToString() is called
  2. the collaborating object is not null and returns the expected result
  3. when inspected in the debugger, the objects return the expected result from ToString()

BUT the text does not show up in the form.

The only common thread I see is that these use a collaborating object, whereas the other bindings that show up as expected simply work from properties and methods of the containing object.

If this is confusing, here is the gist in code:

public class ThisThingWorks
{
    private SomeObject some_object;

    public ThisThingWorks(SomeObject s) { some_object = s; }

    public override string ToString() { return some_object.name; }
}

public class ThisDoesntWork
{
    private Formatter formatter;
    private SomeObject some_object;

    public ThisDoesntWork(SomeObject o, Formatter f) 
    {
        formatter = f; 
        some_object = o;
    }

    public override string ToString()
    {
        return formatter.Format(some_object.name);
    }
}

Again, let me reiterate -- the ToString() method works in every other context -- but when I bind to the object in WPF and expect it to display the result of ToString(), I get nothing.

Update:

The issue seems to be what I see as a buggy behaviour in the TextBlock binding. If I bind the Text property to a property of the DataContext that is declared as an interface type, ToString() is never called. If I change the property declaration to an implementation of the interface, it works as expected. Other controls, like Label work fine when binding the Content property to a DataContext property declared as either the implementation or the interface.

Because this is so far removed from the title and content of this question, I've created a new question here: http://stackoverflow.com/questions/2917878/why-doesnt-textblock-databinding-call-tostring-on-a-property-whose-compile-tim

changed the title: http://stackoverflow.com/questions/2917878/wpf-binding-behaviour-different-when-bound-property-is-declared-as-interface-vs-c

A: 

Try these simple changes:

First test your program with this version of the method:

public override string ToString()
{
    return "This method's really being called."
}

If that actually displays something in the UI, now try this version:

public override string ToString()
{
    Console.WriteLine(
       string.Format("some_object.name = {0}, formatter.Format(some_object.name) = {1}",
          some_object.name,
          formatter.Format(some_object.name));
    return formatter.Format(some_object.name);
}

If this doesn't lead you to figure out what's really wrong, I'll be extremely surprised.

Robert Rossney
@robert Thank you for your answer. I went down this route before, but wasn't able to track down the issue. As it turns out, the behaviour is different depending on whether the property to which I am binding is declared with an interface type or a class type. I updated the question with a link to steps to reproduce the behaviour.
Jay
A: 

Well following on from my comment to your question, you are using the fact that WPF will fall-back to ToString if you do not directly bind it to something e.g. a property on an object. Using the fall-back behaviour of ToString is not really the WPF way - expose a real object and bind to a real property and you'll be fine.

The problem - IFoo does not have a ToString member...

Update

Although IFoo does not have ToString as a member, all objects that implement obviously do...

See my updated answer:

http://stackoverflow.com/questions/2917878/wpf-binding-behaviour-different-when-bound-property-is-declared-as-interface-vs-c/2917932#2917932

chibacity