Firstly I have a user control which has a dependency property as follows. The MenuItems property is bound to some List control on the UI.
public static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(
nameof(MenuItems),
typeof(IEnumerable<MenuItem>),
typeof(MenuViewControl),
new PropertyMetadata(null));
public IEnumerable<MenuItem> MenuItems
{
get => (IEnumerable<MenuItem>)GetValue(MenuItemsProperty);
set => SetValue(MenuItemsProperty, value);
}
The MenuItem class is as follows which has 3 properties,
public class MenuItem : BindableBase
{
private string _text;
private Action _action;
private ICommand _executeCommand;
public string Text
{
get => _text;
set => Set(ref _text, value);
}
public Action Action
{
get => _action;
set => Set(ref _action, value);
}
public ICommand ExecuteCommand
{
get => _executeCommand ?? (_executeCommand = new RelayCommand(Action, _canExecute));
set
{
if (Set(ref _executeCommand, value))
{
CanExecute = () => _executeCommand?.CanExecute(null) ?? true;
_executeCommand.CanExecuteChanged += (sender, args) => RaisePropertyChanged(nameof(IsEnabled));
}
}
}
}
Now somewhere in my code I want to reuse the above user control. Along the same lines I need to call some async methods. So I have a view model class for the current UI where I will be calling the above user control as follows. My problem is the IsBorderProgressRingVisible is never being set to false and the RunMethodResult never updates the TextBlock in the current UI. Please help.
public class UserMaintenanceMethodsViewModel:BindableBase
{
//This collection is bound to the above UserControl's MenuItem property on my current UI.
private ObservableCollection<MenuItem> _userMaintenanceMenuCollection;
public ObservableCollection<MenuItem> UserMaintenanceMenuCollection
{
get => _userMaintenanceMenuCollection;
set => Set(ref _userMaintenanceMenuCollection, value);
}
//This string is bound to a textblock
private string _runMethodResult;
public string RunMethodResult
{
get => _runMethodResult;
set => Set(ref _runMethodResult, value);
}
//This property is bound to a progress ring.
private bool _isBorderProgressRingVisible;
public bool IsBorderProgressRingVisible
{
get => _isBorderProgressRingVisible;
set => Set(ref _isBorderProgressRingVisible, value);
}
//In my constructor I am calling some async methods as follows..
public UserMaintenanceMethodsViewModel()
{
_ = PopulateServiceMethods();
}
//Problem in this method is once the IsBorderProgressRingVisible is set to true, it never sets the value back to false. As a result the progress ring never collapses.
//The other problem is the RunMethodResult which is bound to a textblock never gets updated. Please help.
private async Task PopulateServiceMethods()
{
try
{
if (_atlasControlledModule != null)
{
IsBorderProgressRingVisible = true;
UserMaintenanceMenuCollection = new ObservableCollection<MenuItem>();
var Methods = await _atlasControlledModule.GetServiceMethods(AtlasMethodType.Maintenance).ConfigureAwait(true);
foreach (var method in Methods)
{
UserMaintenanceMenuCollection.Add(new MenuItem()
{
Text = method.Name,
Action = async () =>
{
var result = await ExcuteAtlasMethod(method).ConfigureAwait(true);
RunMethodResult = result.Status.ToString(); //The textblock on the UI never gets updated.
},
Warning = false
});
}
}
}
finally
{
IsBorderProgressRingVisible = false; //This code dosen't work.
}
}
private async Task<AtlasMethodRequest> ExcuteAtlasMethod(AtlasMethod method)
{
try
{
IsBorderProgressRingVisible = true;
return await _atlasControlledModule.CallMethod(method);
}
finally
{
IsBorderProgressRingVisible = false;
}
}
}
Edit: Here is the Xaml for the current view
<viewCommon:PageViewBase
x:Class="Presentation.InstrumentUI.ViewsLoggedIn.UserMaintenanceMethodsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewCommon="using:Presentation.InstrumentUI.Common"
xmlns:viewsCommon="using:Presentation.InstrumentUI.ViewsCommon"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:valueConverters="using:Presentation.Common.ValueConverters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<viewsCommon:MenuViewControl x:Name="UserMaintenanceMethodsMenuView"
Grid.Row="0"
Title="{Binding UserMaintenanceMethodsTitle, Source={StaticResource StringResources}}"
LifetimeScope="{x:Bind LifetimeScope}"
MenuItems="{x:Bind ViewModel.UserMaintenanceMenuCollection,Mode=OneWay}"
HeaderVisibility="Visible">
</viewsCommon:MenuViewControl>
</Grid>
</viewCommon:PageViewBase>
This is the xaml.cs
public sealed partial class UserMaintenanceMethodsView : PageViewBase
{
public IUserMaintenanceMethodsViewModel ViewModel { get; set; }
public UserMaintenanceMethodsView()
{
this.InitializeComponent();
ViewModel = LifetimeScope.Resolve<IUserMaintenanceMethodsViewModel>();
}
}