Geeks With Blogs
Juans and Zeros

I have been beating my head against the desk the last day and a half trying to figure out how to access a UI controls method from an MVVM View Model.  I am using the DevComponents AdvGrid control and the users wanted to have a totals summary row at the bottom of the grid.  I didn’t see in the documentation that this was something supported out of the box but did see an option to pin an item but the method wasn’t able to have a binding to a view model property, so I ventured out to figure out a solution. 

With some research, later coming across this blog post about Using Bing Maps SetView method with MVVM and suggestions from co-workers I decided on using the MVVM Light Messenger component.  From what I understand the messenger class can be used to communicate within the application fairly easily.

From the samples I saw it looked like I could use a Messenger.Default.Send from my View Model to publish a message and then in the code behind of a view use Messenger.Default.Register to listen and receive the message and act on it.  Initially I had the AdvGrid in a Resource Dictionary with the rest of my UI controls.  I created a code-behind file for the ResourceDictionary from this StackOverflow question and answer but with several unsuccessful attempts of trying to get access to the AdvGrid and its methods I decided that I would create a User Control View that had the grid in it, then I was able to get to the control from the code-behind.

In the constructor of my view I am using the MvvmLight messenger like so:

public MyView()
{      
     InitializeComponent();  
    
     // ContractResult is an item added to an abservable collection  
     Messenger.Default.Register<ContractDisbursementResult>(this, PinItem);
}

And the PinItem method is:

private void PinItem(ContractDisbursementResult item)
{
      // Grid = x:Name="Grid" in XAML for the AdvGrid
      // PinItem is the method from AdvGrid
      Grid.PinItem(item, RowPin.Bottom);
}

I also created a View Model to support the View which only has a public  ObservableCollection that is bound to the AdvGrid ItemsSource.

private ObservableCollection<ContractDisbursementResult> _contractDisbursements;

public ObservableCollection<ContractDisbursementResult> ContractDisbursements
{
            get
            {
                return _contractDisbursements;
            }
            set
            {
                SetPropertyValue(value, ref _contractDisbursements, "ContractDisbursements");
            }
}

Then from my Contract Edit view model I wire it all together to send the message.

private readonly ILoanManagementServiceAgent _loanManagementServiceAgent;
public ContractDisbursementsListViewModel ContractDisbursementsListViewModel { get; set; }

// Constructor
public ContractEditViewModel(ILoanManagementServiceAgent loanManagementServiceAgent)
{
    _loanManagementServiceAgent = loanManagementServiceAgent;
     ContractDisbursementsListViewModel = new ContractDisbursementsListViewModel();
}

public Contract SelectedContract
{
            get { return _selectedContract; }
            set
            {
                SetPropertyValue(value, ref _selectedContract, "SelectedContract");
                GetContractDisbursementsAsync();
            }
}

private async void GetContractDisbursementsAsync()
{
            if (SelectedContract == null) return;
            var disbursements =
                await _loanManagementServiceAgent.GetDisbursementsByContractI(SelectedContract.ContractId, CutOffDate);

            ContractDisbursementsListViewModel.ContractDisbursements = disbursements;
            CreateDisbursementsSummary();
 }

private void CreateDisbursementsSummary()
{
            var summary = new ContractDisbursementResult
                              {
                                  ServicerName = "Totals",
                                  TotalAmount =
                                      ContractDisbursementsListViewModel.ContractDisbursements.Sum(result => result.TotalAmount)
                              };

            ContractDisbursementsListViewModel.ContractDisbursements.Add(summary);
            OnPropertyChanged(() => ContractDisbursementsListViewModel.ContractDisbursements);

            Messenger.Default.Send(summary);
 }

 

Now when I run the WPF application and look at the screen the AdvGrid has a totals summary row pinned to the bottom of the grid that doesn’t move when users sort by columns.  Thanks to MVVM Light and the messenger class it made something that seemed impossible to do at first end up not very difficult at all.

I hope this post helps other developers that are trying to figure out how to communicate with UI controls methods that aren’t accessible from MVVM view models.

Posted on Friday, January 25, 2013 10:38 AM MVVM , MVVM Light | Back to top


Comments on this post: Accessing a UI control’s method using MVVM Light Messenger

No comments posted yet.
Your comment:
 (will show your gravatar)
 


Copyright © JuansAndZeros | Powered by: GeeksWithBlogs.net | Join free