Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Как в WPF можно в зависимости от роли пользователя сделать видимость элементов?

Руслан Сафин Знаток (430), открыт 7 часов назад
Приведу для примера свой код, который был бы хорошим вариантом, если бы работал.
В моем случае у меня все везде правильно привязано и обновляются данные (Вызывается RaisePropertyChanged при обновлении) и Views отрисовывают роль пользователя в профиле. Но почему-то не обновляется видимость элементов.
 <Button Content="Пользователи" Command="{Binding GoToCommand}" 
CommandParameter="{x:Static viewModels:Pages.Users}" Visibility="Collapsed">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource Fok.SolidButton}">
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentPage.Value}"
Value="{x:Static viewModels:Pages.Users}">
<Setter Property="Background" Value="{StaticResource Fok.SecondaryBrush}" />
</DataTrigger>
<DataTrigger Binding="{Binding UserRole.Value}"
Value="{x:Static users:Roles.Admin}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Хотел поинтересоваться есть ли какой-то элегантное решение для этой задачи?
2 ответа
taror Ученик (234) 3 часа назад
Ваш код уже использует `DataTrigger`, что является хорошим подходом. Однако, если видимость не обновляется, возможно, что `UserRole` не вызывает обновление интерфейса. Убедитесь, что `UserRole` реализует `INotifyPropertyChanged`. Вот пример:

```csharp
public class UserViewModel : INotifyPropertyChanged
{
private Role _userRole;

public Role UserRole
{
get => _userRole;
set
{
if (_userRole != value)
{
_userRole = value;
OnPropertyChanged(nameof(UserRole));
}
}
}

// Реализация INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
```

### 2. Использование `BooleanToVisibilityConverter`

Вы можете создать `IValueConverter`, который будет преобразовывать роль пользователя в видимость элемента. Например:

```csharp
public class RoleToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Role role)
{
return role == Roles.Admin ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}

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

Затем используйте этот конвертер в XAML:

```xml
<Window.Resources>
<local:RoleToVisibilityConverter x:Key="RoleToVisibilityConverter"/>
</Window.Resources>

<Button Content="Пользователи" Command="{Binding GoToCommand}"
CommandParameter="{x:Static viewModels:Pages.Users}"
Visibility="{Binding UserRole, Converter={StaticResource RoleToVisibilityConverter}}">
</Button>
```

### 3. Использование `MultiBinding`

Если вам нужно учитывать несколько свойств для определения видимости, вы можете использовать `MultiBinding` с `IMultiValueConverter`. Вот пример:

```csharp
public class RoleAndPageToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] is Role role && values[1] is Page currentPage)
{
if (role == Roles.Admin)
{
return Visibility.Visible;
}
}
return Visibility.Collapsed;
}

public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
```

Затем используйте `MultiBinding` в XAML:

```xml
<Button Content="Пользователи" Command="{Binding GoToCommand}"
CommandParameter="{x:Static viewModels:Pages.Users}">
<Button.Visibility>
<MultiBinding Converter="{StaticResource RoleAndPageToVisibilityConverter}">
<Binding Path="UserRole"/>
<Binding Path="CurrentPage.Value"/>
</MultiBinding>
</Button.Visibility>
</Button>
```
Похожие вопросы