IValueConverter refresh

1

I am implementing a menu with security, so that according to the security of the user you will see or not the menu items.

For this I have an entity called UserSecurity of the form:

public class UserSecurity :BaseEntity
{
    public int? UserSecurityId { get; set; }

    public int? UserId
    {
        get
        {
            return GetValue(() => UserId);
        }
        set
        {
            SetValue(() => UserId, value);
        }
    }

    public string MenuName
    {
        get
        {

            return GetValue(() => MenuName);
        }
        set
        {
            SetValue(() => MenuName, value);
        }
    }

    public bool Visibility
    {
        get
        {

            return GetValue(() => Visibility);
        }
        set
        {
            SetValue(() => Visibility, value);
        }
    }

}

where BaseEntity contains the implementation of INotifyPropertyChanged through GetValue () and SetValue (). This security is associated to the user of the form:

 public class User : BaseEntity
{
    public int? UserId { get; set; }

    public bool Active
    {
        get
        {

            return GetValue(() => Active);
        }
        set
        {
            SetValue(() => Active, value);
        }
    }

    public string UserName
    {
        get
        {

            return GetValue(() => UserName);
        }
        set
        {
            SetValue(() => UserName, value);
        }
    }


    public virtual ICollection<UserSecurity> UserSecurities
    {
        get
        {
            return GetValue(() => UserSecurities);
        }
        set
        {
            SetValue(() => UserSecurities, value);
        }
    }
}

Users and their security are activated when they log in to the application, and they work correctly through a CustomConverter:

public class PermissionToVisibilityConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        string propertyName = parameter as string;

        if (String.IsNullOrWhiteSpace(propertyName))
            return value;

        foreach(var security in user.UserSecurities)
        {
            if (security.MenuName == propertyName)
                return (security.Visibility == true ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
        }

        return value;

    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

}

where user is a global variable that contains the user's data and its security. The visibility in the menu is implemented in the following way:

Visibility="{Binding Converter={StaticResource ptvConverter}, ConverterParameter=Company}"

Although this implementation works correctly, now I want that, if I modify the security, the corresponding menus are shown or hidden. To do so, I reload the user object, which does not mean that the changes are updated at the visual level.

How can I make the UI layer see those changes and "recalculate" the visibility value with the CustomConverter?

Thank you.

    
asked by Alvaro 24.10.2016 в 14:04
source

2 answers

0

You have the problem in the form of bindear la visibilitty. I'll explain, you're doing a blind binding, and the converter does not jump again, when the value changes. This error has led you to use the static class. This static class must be received inside the value parameter of the converter, for it to detect it.

Visibility="{Binding Converter={StaticResource ptvConverter}, ConverterParameter=Company}"

This binding has missing the Path property, something like this:

Visibility="{Binding Path="Model.Campo_INotifyPropertyChanged", Converter={StaticResource ptvConverter}, ConverterParameter=Company}"

Bone, that you either have to create a property in your ViewModel, I suppose you will be using MVVM, and assign it your User (Static), or you will directly binde the static field with {x: static ...} in the binding .

    
answered by 07.11.2016 в 17:55
0

To update the UI when changing the values of an object and WITHOUT needing to reload the object you must correctly implement INotifyPropertyChanged, and this will be done in the SET of each property, after assigning the value you add another line to tell to the UI to be updated .. your implementation is a bit strange for me, but the concept is this ..

So you have it

set
{
  SetValue(() => UserSecurities, value);
}

That's how it should be:

set
{
  SetValue(() => UserSecurities, value);
   if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("MyProperty"));
}

Then every time there is a change the UI will be updated, for this you must -as I already said- implement INotifypropertyChanged in all the classes involved so that the change is transmitted until arriving at the interface.

    
answered by 07.12.2016 в 03:01