wpf - wpf 动态用户安全
问题描述
该软件使用包含 SecurityRole 对象的 SmartSnowUser 对象。客户端需要 SecurityRole 是可定制的,因此它有一个枚举 SecurityTasks 列表,客户端可以从中添加/删除。仅当给定的 SecurityTask 存在于当前 SmartSnowUser 的 SecurityRole 中时,控件才应可见。
使用此设置,我正在努力获得所需的所有功能。我需要具备以下能力:
- 根据 CurrentUser.Role 是否包含 GivenTask 更改控制可见性
- 必要时使控件可见性更精细(例如可见性 &= isInEditMode)
- 满足前两个要求,而不必为每个颜色/任务/额外限定符组合创建单独的样式
这是我尝试过的两种主要方法。
尝试#1:
当前问题:未触发可见性;Convert() 方法中的断点永远不会被命中
长期问题:使用样式,因此所有其他自定义样式都需要基于此默认值;此外,必须复制功能以实现可编辑性
代码:
/**Style.xaml**/
<local:TagToVisibilityConverter x:Key="TagToVisibilityConverter"/>
<Style TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource TagToVisibilityConverter}">
<Binding Path="MainData.CurrentUser"/>
<Binding RelativeSource="{RelativeSource Mode=Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
/**Style.xaml.cs**/
public class TagToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length >= 2 && (values[1] as FrameworkElement).GetValue(SecurityLevel.RequiredTaskProperty) is SecurityTask requiredTask)
{
//If element has a task assigned and user is not logged in, do not show
if (values[0] is SmartSnowUser currentUser && currentUser.Role != null)
{
return currentUser.Role.Tasks.Contains(requiredTask) ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}
//If element has no task assigned, default to visible
return Visibility.Visible;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class SecurityLevel
{
public static readonly DependencyProperty RequiredTaskProperty = DependencyProperty.RegisterAttached("RequiredTask", typeof(SecurityTask), typeof(FrameworkElement), new PropertyMetadata(SecurityTask.ControlBasic));
public static void SetRequiredTask(UIElement element, SecurityTask value)
{
element.SetValue(RequiredTaskProperty, value);
}
public static SecurityTask GetRequiredTask(UIElement element)
{
return (SecurityTask)element.GetValue(RequiredTaskProperty);
}
}
/**Implementation in User Control**/
<Button Name="BtnNew" Content="Create New Role" Style="{StaticResource ButtonBlue}" server:SecurityLevel.RequiredTask="{x:Static enums:SecurityTask.EditRoles}" />
尝试#2:
如何将依赖属性添加到 WPF 中的 FrameworkElement 驱动类?
试图将这两种解决方案合并为一个。将 Tag 值设置为 SecurityTask,然后使用触发器设置可见性
问题:无法在没有样式的情况下设置更细粒度的可见性(例如,无法直接在控件中设置“可见性”属性);无法区分可见性/可编辑性
代码:
/**Style.xaml**/
<!--#region Visibility-->
<!-- Default frameworkElement style definition -->
<local:TagToVisibilityConverter x:Key="TagToVisibilityConverter"/>
<Style TargetType="{x:Type FrameworkElement}">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource TagToVisibilityConverter}">
<Binding Path="Tag" RelativeSource="{RelativeSource Mode=Self}"/>
<Binding Path="MainData.CurrentUser"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
<!-- Extending default style -->
<Style x:Key="ButtonBasic" TargetType="Button" BasedOn="{StaticResource {x:Type FrameworkElement}}">
<Setter Property="Background" Value="{StaticResource BrushGreyDark}" />
<Setter Property="Foreground" Value="{StaticResource BrushWhite}" />
</Style>
<Style x:Key="ButtonBlue" TargetType="Button" BasedOn="{StaticResource ButtonBasic}">
<Setter Property="Background" Value="{StaticResource BrushBlue}" />
</Style>
/**Style.xaml.cs**/
public class TagToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length >= 2 && values[0] is SecurityTask requiredTask)
{
//If element has a task assigned and user is not logged in, do not show
if (values[1] is SmartSnowUser currentUser && currentUser.Role != null)
{
return currentUser.Role.Tasks.Contains(requiredTask) ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}
//If element has no task assigned, default to visible
return Visibility.Visible;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
/**Implementation in User Control**/
//This button works great. Exactly what I need.
<Button Name="BtnNew" Content="Create New Role" Style="{StaticResource ButtonBlue}" Tag="{x:Static enums:SecurityTask.EditRoles}" />
//This button does not work, because the newly set Visibility property overrides the style.
<Button Name="BtnEdit" Content="Edit Role" Style="{StaticResource ButtonBlue}" Tag="{x:Static enums:SecurityTask.EditRoles}" Visibility="{Binding IsEditMode, Converter={StaticResource InverseBoolToVisibilityConverter}}" />
尝试#2 几乎可以工作。这是最后一个臭按钮,BtnEdit。创建一个新样式太混乱了——BasedOn ButtonBlue,它是BasedOn ButtonDefault,它是我们原来的BasedOn——每次我需要在我的可见性设置中添加另一个限定符时。
我似乎过于复杂了。对于我正在尝试做的事情,是否有更清洁的方法?
解决方案
推荐阅读
- android - Android Studio 模拟器错误“AVD 的模拟器进程被杀死”
- search - Laravel scout (meilisearch-driver) 搜索多对多关系
- asp.net-core - 如何将 MassTransit 传奇子步骤与替代拓扑集成?
- python - 一个熊猫单元格中的熊猫数据系列
- swift - 如果在 MKMapView visibleMapRect 中可见,则加载注释
- python - 以 CSV(或文本)格式导出 Weka 命令行预测,仅预测值和原始值
- c# - 如何将我的枚举描述值分配给变量?我是新手
- android - Android NDK 值有时为空
- python - 如何使用 GPU 运行经过训练的 Yolov3 模型
- java - 如何使用 poi 将外部页眉页脚文件(.xml 格式)添加到现有 .docx 文档