hide menu links after login

May 13, 2013 at 5:38 PM
Edited May 13, 2013 at 5:39 PM
I'm trying to create a login page which should disappear after login and displays the program pages.

This is MainView.xaml:
<mui:ModernWindow.MenuLinkGroups>
    <!-- Pages/Login.xaml contains the login logic, method shown below -->
    <!-- The link group GroupName="credentials" should disappear after login -->
    <mui:LinkGroup DisplayName="Welcome" GroupName="credentials">
        <mui:LinkGroup.Links>
            <mui:Link DisplayName="login" Source="Pages/Login.xaml"/>
        </mui:LinkGroup.Links>
    </mui:LinkGroup>
    <!-- The link group GroupName="program" should appear after login -->
    <mui:LinkGroup DisplayName="Welcome" GroupName="program">
        <mui:LinkGroup.Links>
            <mui:Link DisplayName="dashboard" Source="Pages/Dashboard.xaml"/>
        </mui:LinkGroup.Links>
    </mui:LinkGroup>
</mui:ModernWindow.MenuLinkGroups>
The Login.xaml pages has a button which triggers the following method in the LoginViewModel:
public class LoginViewModel : NotifyPropertyChanged
{
    private void Login(object commandParameter)
    {
        var passwordbox = commandParameter as PasswordBox;
        if (passwordbox != null)
        {
            // Validate credentials against webservices
            // Set login flag
            // deactivate login views, activate normal menu links
        }
    }
}
How can i deactivate link groups and activate other from a viewmodel?
Coordinator
May 13, 2013 at 10:02 PM
Edited May 13, 2013 at 10:04 PM
Move your menu links to the view model and fill them based on whatever business logic you have. Something like this works:
public class MyViewModel : NotifyPropertyChanged
{
  public MyViewModel()
  {
    this.MenuLinkGroups= new LinkGroupCollection()
    UpdateMenu();
  }
  public LinkGroupCollection MenuLinkGroups{ get; private set; }

  private void UpdateMenu()
  {
    this.MenuLinkGroups.Clear();
    if (this.loggedIn){
      // fill with groups when logged in
      this.MenuLinkGroups.Add(..);
    }
    else {
      // fill with groups when not logged in
      this.MenuLinkGroups.Add(..);
    }
  }
}
And your xaml (assuming MyViewModel is set as DataContext):
<mui:ModernWindow MenuLinkGroups="{Binding MenuLinkGroups}"
</mui:ModernWindow>
Since the LinkGroupCollection derives from ObservableCollection<T> any updates are automatically applied to the view when bound.
May 14, 2013 at 10:30 AM
works fine thank you!

One more question: How can i select the first link from the first linkgroup by default?

I tried to bind the ContentSource of the ModernWindow to an Uri in my ViewModel.
ViewModel
        private Uri startpage;
        public Uri Startpage
        {
            get { return this.startpage; }
            set
            {
                this.startpage = value;
                this.OnPropertyChanged("Startpage");
            }
        }
Xaml:
<mui:ModernWindow ContentSource="{Binding Startpage, Mode=OneWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
</mui:ModernWindow>
Doesn't work so far, it behaves like an OneTime Binding.
Coordinator
Jun 7, 2013 at 6:11 PM
Edited Jun 7, 2013 at 6:16 PM
Your approach looks correct. Are you sure the uri value exists in the link sources defined in XAML? Also, make sure that the link sources are unique among all link groups in the xaml.

Any binding errors in the output window?
Jun 10, 2013 at 11:11 AM
No errors in the output window, i created this demo project to illustrate the problem.
Coordinator
Jun 10, 2013 at 12:05 PM
The problem in your demo project is that the links added to the link groups are prefixed with a '/' where the selected link is not. The link uri's simply don't match, either both should have a '/' prefix or remove it from both.

Furthermore; you do not need to clear the link groups. Just add all groups and links to the MenuLinkGroups and select the link you need. The LinkGroup.GroupName is used for grouping the linkgroups.

So split your UpdateMenu in two, invoke CreateMenu from the constructor and you are all set.
public MainViewModel()
{
  this.MenuLinkGroups = new LinkGroupCollection();
  this.ToggleMenuCommand = new RelayCommand(this.ToggleMenu);
  this.CreateMenu();
}

private void CreateMenu()
{
  this.MenuLinkGroups.Clear();

  var linkTestGroup1 = new LinkGroup { DisplayName = "TestGroup1", GroupName = "test1" };
  var link1 = new Link { DisplayName = "Link 1", Source = new Uri("/Pages/Link1.xaml", UriKind.Relative) };
  linkTestGroup1.Links.Add(link1);
  this.MenuLinkGroups.Add(linkTestGroup1);

  var linkTestGroup2 = new LinkGroup { DisplayName = "TestGroup2", GroupName = "test2" };
  var link2 = new Link { DisplayName = "Link 2", Source = new Uri("/Pages/Link2.xaml", UriKind.Relative) };

  linkTestGroup2.Links.Add(link2);

  this.MenuLinkGroups.Add(linkTestGroup2);

  UpdateMenuSelection();
}

private void UpdateMenuSelection()
{
  if (!this.ButtonClicked) {
    this.SelectedLink = new Uri("/Pages/Link1.xaml", UriKind.Relative);
  }
  else {
    this.SelectedLink = new Uri("/Pages/Link2.xaml", UriKind.Relative);
  }
}

private void ToggleMenu(object parameter)
{
  this.ButtonClicked = !this.ButtonClicked;
  this.UpdateMenuSelection();
}
Jun 10, 2013 at 1:24 PM
Thanks a lot, it is working now :)
Jul 11, 2013 at 1:07 AM
Hi Guys,

Does anyone know how this could be done with a datatrigger, ie on a boolean change the menulinkgroup in xaml.

I am trying to keep the view separate from the viewmodel and keeping the LinkGroupCollection in the viewmodel breaks that.

I am not sure if it is possible but it would be good to have a window resource of possible menus and switch between them using a datatrigger or something like that.

Anyone know if this is possible?

something like this (i know this doesn't work but just an example of what I mean).
<<Style BasedOn="{StaticResource {x:Type mui:ModernWindow}}">
        <Style.Triggers>
            <DataTrigger on backend value == true>
                <Setter Property="" Value="{Binding groupA}"></Setter>
            </DataTrigger>
            <DataTrigger on backend value == false>
                <Setter Property="" Value="{Binding groupB}"></Setter>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <Window.Resources>
        <mui:LinkGroup x:Name="groupA" DisplayName="Welcome" GroupName="credentials">
            <mui:LinkGroup.Links>
                <mui:Link DisplayName="login" Source="Pages/Login.xaml"/>
            </mui:LinkGroup.Links>
        </mui:LinkGroup>
         The link group GroupName="program" should appear after login 
        <mui:LinkGroup x:Name="groupB" DisplayName="Welcome" GroupName="program">
            <mui:LinkGroup.Links>
                <mui:Link DisplayName="dashboard" Source="Pages/Dashboard.xaml"/>
            </mui:LinkGroup.Links>
        </mui:LinkGroup>
    </Window.Resources>
Cheers
Sep 5, 2013 at 9:04 AM
Edited Sep 5, 2013 at 9:04 AM
Is it possible to share a example src of a login method ?
I have some difficulty to understand this thread

Thanks by advance
SheppeR
Coordinator
Sep 5, 2013 at 5:01 PM
Why is keeping the LinkGroupCollection in the view model breaking your MVVM model? LinkGroupCollection itself is not a visual.
Oct 30, 2014 at 9:51 AM
Hi
I am having trouble implementing the code from kozw and the demo project from Xenolith is not available on skydrive. Could someone please provide me with a demo project with this implementation..

What i am trying to do is this, when the application loads, it displays the login page link only. The settings link should be greyed or inactive. Then when a user logs in successfully, only links associated with a user role are displalyed. Example if Administrator logs in, all links become available.

I will greatly appreciate any help.
Dec 31, 2014 at 7:50 AM
I am also applying a log in logic. But cannot place it in the main window, because only content source is shown when program starts. I Implemented log in Logic in a user control and set it as content source. However, from the control I cannot access MainWindowViewModel to call the method that constructs Menu Link Groups.

Thanks in advance.
Nov 20, 2015 at 4:06 PM
Hy...
I have no idea how to binding that ViewModel to my project,

I already creat ViewModel like MyModelView sample modelView from kwoz, and i have add binding to my modernWindow.xaml to,
<mui:ModernWindow MenuLinkGroups="{Binding MenuLinkGroups}"
</mui:ModernWindow>

But than my ModernWindow get error,
Can some one give a sample demo how to hide or add MenuLinkGroups...

Sorry about my language, i'm from indonesia.