简体   繁体   中英

WPF Method binding to get() and set(value) instead of properties

Is there any way to use binding which directly interacts with methods to get a value and set its value?

I have a class which has methods instead of properties

public class Foo
        {
            public object GetProp1()
            {
                //some logic
                return someObject;
            }
            public object GetProp2()
            {
                //some logic
                return someObject;
            }

            public object SetProp1(object someObject)
            {
                //some logic               
            }

            public object SetProp2(object someObject)
            {
                //some logic
            }
        }

To achieve data binding, I'm declaring properties for each function and calling model's method

public class FooViewModel
        {
            Foo foo = new Foo();
            public object Prop1
            {
                get => foo.GetProp1();
                set => foo.SetProp1(value);
            }
            public object Prop2
            {
                get => foo.GetProp2();
                set => foo.SetProp2(value);
            }
        }

Problem is if I have 50 methods, in Foo, I need to create approx 50 properties in ViewModel. Is there any other way to eliminate properties in ViewModel just to bind with View?

Something like this: Textbox will set its value and Label will display

<TextBox Text="{MethodBinding MethodName=foo.SetProp1}"/> 
<Label Content="{MethodBinding MethodName=foo.GetProp1}"/> 

You can technically manage to bind to methods if you really put your mind to it but I don't think that's a very helpful answer.

In any commercial team I've worked in, doing this would see your MR/PR rejected. It is widely considered bad practice.

What I would recommend is make those properties regular properties raising property changed. Get your data for them in async tasks.

If you define an interface you can then give all your Getting-Data Tasks the same name and generically invoke them on any viewmodel you instantiate.

In some real world code I have, I call this Task Initiate.

interface IInitiatedViewModel
{
    Task Initiate();
}

Here's one such task ( slightly simplified ) out one of my viewmodels:

    public async Task Initiate()
    {
        DateFrom = LastApril();
        Transactions = await repository.GetFlattenedTransactionsAsync(DateFrom, DateTo);
    }

Transactions is a public property a Datagrid is bound to.

Process is therefore to instantiate my ViewTransactionsViewModel. It comes out a DI container but let's not digress too far.

I can present that viewmodel to the UI and it is templated out into a View.

It has no data initially.

Then await Initiate.

That sets my properties with data.

In more complicated scenarios, Initiate could start multiple threads with Tasks. Arranging data might be quite expensive so a Task (or many ) could be started on another thread.

A common variation is to have a base viewmodel which exposes an IsBusy bool. That is used to flag commands and drive a busy spinner. That would initially be true. Your view would render with a spinner. The last line of Initiate would be to set IsBusy false. The spinner would disappear and the date would be rendered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM