Search code examples
c#asynchronousivalueconverterdomainservices

Problems with IValueConverter and asynch DomainService Invoke in C#


In my searching the common solution to this problem is to add an event handler to handle once the invoke operation has completed.

Unfortunately, my IValueConverter needs to return a value so having the handler is not much help. I have also tried a do/while loop until the operation is complete but the loop never closes.

I have also tried just a simple wait operation but it still returns null. I know that my DomainService returns the correct value but the Converter never gets to see it.

Is there anything I can do in this instance? Having a converter that works would remove/reduce pretty much all future problems I can forsee.

My code: (i need something like this that works)

    InspectDomainContext context = new InspectDomainContext();
    string name;
    InvokeOperation<string> inv;

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string id = (string)value;
        inv = context.GetName(id);
        inv.Completed += new EventHandler(inv_Completed);
        // return here after the handler has completed
        return name;
    }

    void inv_Completed(object sender, EventArgs e)
    {
        name = inv.Value;
    }

Solution

  • (new answer as it's completely different to the first one!)

    This presumes you're using some sort of ViewModel datacontext pattern...

    Rather than do this in an IValueConverter, you can create a second property on your ViewModel to hold the converted value.

    public class MyViewModel
    {
        private string _id;
        public string Id
        {
            get { return _id; }
            set 
            { 
                _id = value; 
                UpdateConvertedName(_id);
            }
        }
    
        private void UpdateConvertedName(string id)
        {
            // Same as your 'Convert' code above
        }
    
        private void inv_Completed(object sender, EventArgs e)
        {
            Name = inv.Value;        
        } 
    
        public string Name { get; set; }
    }
    

    So instead of binding to ID with a converter, you'd just bind directly to Name. Whenever ID is changed, Name will be updated asynchronously. You may also need some INotifyPropertyChanged in the Name getter/setter, if you're using ViewModels you'll already be familiar with all of that.

    As you're stuck with asynchronous calls, it could also be worth adding some UI indicators that a value is old or incomplete - I don't know what your setup is, but theoretically the client machine could be on a 28.8k connection from the other side of the world or a very slow mobile device, so your response time would be very poor. But that's not really relevant to the answer at hand!