Automatic BusyIndicator for asynchronous operations and more

    Using such a component as BusyIndicator will bring to our application pleasant (process indication) and useful (control blocking) qualities. However, until recently, I rarely used it, because when receiving the data source asynchronously, I had to constantly write additional code to turn it on / off. With synchronous operation, the situation seems to be simplified, but the use of the MVVM model still requires additional body movements. Especially if BusyIndicatoradded at the very end of form development.

    Therefore, I decided to automate this process as much as possible so that I did not have to write a single line of code. So:

    Problem statement:
    1. Provide automatic indication for any lists that use the property value as a data source ItemsSource.
    2. A sign that the data obtained will be considered not an empty value of the property ItemsSource.
    3. As a BusyIndicator'you can use any control if only it had a booleanproperty IsBusy.
    4. All additional coding should be implemented in the view of the form and the XAML code should have the following template:
      
              ...
          


    The binding property IsAsync=truein the example can be omitted, in this case the reasoning does not change much, but in this article I will give examples of exactly asynchronous data acquisition, because if an indication of the process is required, then obtaining data takes a tangible time, and if so, then we don’t want our application to freeze at the same time, and if so, asynchronous binning is everything. Moreover, it costs us nothing to implement it: IsAsync = true in XAML and in ViewModel’s code:

    private IEnumerable _dataList = null;
    public IEnumerable DataList
    {
        get
        {
            if (_dataList == null)
                _dataList = Model.GetDataList(...);
            return _dataList;
        }
        private set
        {
            if (_dataList == value) return;
            _dataList = value;
            NotifyPropertyChanged("DataList");
        }
    }
    public void RefreshDataList()
    {
        DataList = null;
    }
    


    The first thing that occurred to me (and it even worked visually) was to write something like this:
    
            ...
        


    Well, who can immediately criticize this code?

    So I also did not like him at once. Debugging confirmed my concerns: the list was received twice - forBusyIndicatorаand for the list.

    “It doesn’t matter!” I said, and slightly changed the method of obtaining the list:
    private object _dataListSync = new nbject();
    private IEnumerable _dataList = null;
    public IEnumerable DataList
    {
        get
        {
            lock (_dataListSync)
            {
                if (_dataList == null)
                    _dataList = Model.GetDataList(...);
                return _dataList;
            }
        }
    }
    


    Now the data was received once and everything worked as intended, but I still did not like this method.

    Firstly, you need to register the converter, secondly, write quite a lot of identical buccaffs , not forgetting to synchronize the list and indicator bindings, if something changes suddenly, thirdly, I'm not sure that receiving DataListfor an indicator is always called before receiving DataList for list.

    The next idea was to use attached property.

    So far, I have not been given the opportunity to understand this deeply with a real interesting example, so in the next article, Creating an Attached Property for BusyIndicator, I will tell you step-by-step what I did.

    Thanks to those who read to the end.

    Also popular now: