WPF将IsEnabled绑定到视图模型

时间:2016-04-11 19:47:27

标签: c# wpf data-binding

我正在开发一个WPF应用程序,该应用程序使用声明来控制用户是什么,不允许做什么。要求是禁用用户无权访问的控件。在我们的基本视图模型中,我们有以下方法:

HasClaim(string name);

我想在观点中做这样的事情:

<button IsEnabled="{Binding HasClaim("NAME")}" />

我知道我可以使用ObjectDataProvider,但我不想为每个声明创建一个。

2 个答案:

答案 0 :(得分:3)

如果您经常在视图中执行此操作,请考虑使用标记扩展。您很可能不需要查看或查看模型中的任何信息来检查用户是否具有正确的声明,通常这些信息是在登录时获取的,并且不依赖于具体视图。

document.getElementById

然后只是:

sed -e 's/2016\(..\)\(..\)/2016-\1-\2/g' input >output

在不太可能的情况下,您确实需要访问您的视图模型,您仍然可以这样做:

public class HasClaimExtension : MarkupExtension {
    private readonly string _name;
    public HasClaimExtension(string name) {
        _name = name;
    }

    public override object ProvideValue(IServiceProvider serviceProvider) {
        return HasClaim();
    }

    private bool HasClaim() {
        // check if user has this claim here
        if (_name.ToLowerInvariant() == "admin")
            return true;
        return false;
    }
}

更新以在评论中回答您的问题。你可以这样做。假设一些简单的LoginManager类:

<Button IsEnabled="{local:HasClaim Admin}" Height="20" Width="100"/>

它有一些关于索赔是否已经可用的指示,以及当这些索赔可用时通知的事件,如果现在它们不可用。然后在您的标记扩展中,首先检查声明是否在此处。如果是 - 只需返回结果。如果不是 - 返回false,但当这些声明可用时将其归入事件。之后 - 用实际值更新目标属性。

public class HasClaimExtension : MarkupExtension {
    private readonly string _name;

    public HasClaimExtension(string name) {
        _name = name;
    }

    public override object ProvideValue(IServiceProvider serviceProvider) {
        var service = (IProvideValueTarget) serviceProvider.GetService(typeof (IProvideValueTarget));
        // this is Button or whatever control you set IsEnabled of
        var target = service.TargetObject as FrameworkElement;
        if (target != null) {
            // grab it's DataContext, that is your view model
            var vm = target.DataContext as MyViewModel;
            if (vm != null) {
                return vm.HasClaim(_name);
            }
        }
        return false;
    }
}

public class MyViewModel {
    public bool HasClaim(string claim) {
        return false;
    }
}

答案 1 :(得分:2)

您可以使用MultiValueConverter并将Button本身及其DataContext作为绑定传递:

<Button Name="someName">
    <Button.IsEnabled>
        <MultiBinding Converter={StaticResource HasClaimConverter}>
            <Binding Path="Name" RelativeSource="{RelativeSource Self}"/>
            <Binding/>
        </MultiBinding>
    </Button.IsEnabled>
</Button>

转换器类:

class HasClaimConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var name= values[0] as String;
        var vm = values[1] as YourViewModel;

        return YourViewModel.HasClaim(name);
    }

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