隐藏基于另一个UserControl元素XAML的元素

时间:2018-09-14 13:44:05

标签: .net wpf xaml

我有一个Window,其内容中有一个UserControl和一个Button。 现在,我想隐藏Button中的RadioButton,具体取决于是否选中UserControl中的<Window x:Class="SimpleMVVMExample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="350" Width="525"> <DockPanel> <local:uc1 x:Name="UserControl1"></local:uc1> <Button Visibility="{Binding IsChecked,ElementName=UserControl1.rb1}"/> </DockPanel> </Window> 。我尝试了以下操作,但没有用。

我的窗口如下:

UserControl

<UserControl x:Class="SimpleMVVMExample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="350" Width="525"> <DockPanel> <RadioButton x:Name="rb1" IsChecked={Binding SomeProperty}/> </DockPanel> </UserControl> uc1看起来像这样:

class IdentifyUserApplicantID(generics.ListAPIView):
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated,]
    queryset = User.objects.all()

def get_queryset(self):
    queryset = User.objects.all()
    applicant = self.request.query_params.get("applicant", None)
    if applicant is not None:
        queryset = queryset.get(applicant=applicant)

    return queryset

    def get(self, request):

        if request.user.user_type == "2":
            try:
                queryset = self.get_queryset()
                serializer = UserSerializer(queryset)
                return Response(jsend.success({'user': serializer.data}))

            except User.DoesNotExist:
                return Response(jsend.success({'user': '[]'}))
        else:
            return Response((jsend.error("You are not authorized to perform 
            this action")),status=status.HTTP_403_FORBIDDEN)

3 个答案:

答案 0 :(得分:2)

您只能绑定到UserControl中的依赖项属性,无法(afaik)那样访问UserControl中的XAML元素,因此您需要做的是在UserControl中定义一个新的Dependency属性,然后将Button的可见性与其绑定在一起。

如果您要创建一个需要向“外部XAML世界”公开信息的UserControl,我认为这就是应该这样做的方式。

UserControl1.xaml.cs:

public static readonly DependencyProperty IsRb1CheckedProperty = 
    DependencyProperty.Register("IsRb1Checked",
    typeof(bool), typeof(UserControl1), new PropertyMetadata(default(bool)));

public bool IsRb1Checked
{
    get => (bool) GetValue(IsRb1CheckedProperty);
    set => SetValue(IsRb1CheckedProperty, value);
}

现在,我们需要将RadioButton绑定到该属性,但是由于UserControl的DataContext是从父级继承的,因此无法立即使用。

您可以将UserControl内的DockPanel的DataContext设置为其自身(不要更改UserControls DataContext),也可以为UserControl命名并在RadioButton绑定中使用ElementName:

让我们继续使用后一种方法,因为它更清晰。

UserControl1.xaml

<UserControl x:Class="WpfPlayground.UserControl1" 
             x:Name="UserControlRoot"
    <RadioButton IsChecked="{Binding ElementName=UserControlRoot, Path=IsRb1Checked}"/>
</UserControl>

我直接将RadioButton绑定到IsRb1Checked,我不知道您的示例中的“ SomeProperty”是什么,但是您可以创建一个包装器属性来设置两个布尔值,甚至更好地使用Checked事件来切换IsRb1Checked。

然后在您的窗口中,请记住使用内置的BooleanToVisibilityConverter:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
</Window.Resources>
<DockPanel>
    <local:UserControl1 x:Name="UserControl1"></local:UserControl1>
    <Button Visibility="{Binding ElementName=UserControl1, Path=IsRb1Checked,
                                 Converter={StaticResource BoolToVisibilityConverter}}"/>
</DockPanel>

关于MVVM的一小段评论:在这种情况下不一定有帮助。我要么被迫提供UserControl自己的ViewModel,然后在父ViewModel中实例化它,要么被赋予UserControl父ViewModel,这将阻止可重用性。最好的方法是公开依赖项属性。

答案 1 :(得分:0)

假设:IsChecked属性为布尔类型。 按钮Visibility接受Visible, Collapsed or Hidden的值。您需要一个布尔值到可见性转换器以使应用程序了解值true或false时需要执行的操作。

创建如下所示的资源。

<Window......>
     <Window.Resources>
          <BooleanToVisiblityConverter x:Key="BooleanToVisibilityConverter"/>
     </Window.Resources>
      .....................
      ....................
</Window>

如下所示更新按钮可见性。

<Button Visibility="{Binding IsChecked,ElementName=UserControl1.rb1, Converter={StaticResource BooleanToVisibilityConverter}"/>

创建一个BooleanToVisibilityConverter,如下所示。

public class BooleanToVisibilityConverter : MarkupExtension, IValueConverter
{
    /// <summary>
    ///     This converter can be used to show, hide and collapse controls.
    ///     It collapse the control if <see cref="collapseIfFalse" /> is true, hides other wise by default.
    /// </summary>
    public object Convert(object value, Type targetType, object collapseIfFalse, CultureInfo culture)
    {
        var collapse = collapseIfFalse is bool && (bool)collapseIfFalse;

        var visible = value is bool && (bool) value;

        return visible
            ? Visibility.Visible
            : collapse ? Visibility.Collapsed : Visibility.Hidden;
    }

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

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

答案 2 :(得分:0)

我了解您问过有关在XAML中执行此操作的问题,但建议您改为在/ model层后面的代码中执行。我将ischecked属性绑定到后面代码中的一个属性,并具有第二个属性,该属性检查其getter中的那个以弄清楚是否应该显示按钮。

npm ci

这样,如果启用或不启用按钮的逻辑发生变化,则可以在代码中添加更复杂的逻辑,而不必费力寻找甚至可以在XAML中完成的逻辑。这样,您还可以将“何时显示”的逻辑与如何显示分开。 XAML变得愚蠢:这就是我呈现数据的方式。有关事物如何工作的业务规则全部以C#/ sql形式进行,无论使用哪种更具表现力的(至少是IMO)语言。