Скрыть элемент на основе другого элемента UserControl XAML - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть 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 uc1 выглядит так:

<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>

Ответы [ 3 ]

0 голосов
/ 18 сентября 2018

Я понимаю, что вы спрашивали об этом в XAML, но я бы посоветовал сделать это в слое code / model. Я бы связал свойство ischecked со свойством в коде и получил бы второе свойство, которое проверяет это свойство в своем геттере, чтобы выяснить, должна ли кнопка отображаться.

public bool IsChecked { get; set; }
public Visibility ButtonVisibility {
get
{
    if ( IsChecked ) ...
}}

Таким образом, если логика для того, когда кнопка включена или не изменяется, вы можете добавить более сложную логику в код, вместо того, чтобы пытаться выяснить, можете ли вы сделать это в XAML. Таким образом, вы также отделяете логику «когда вещи показаны» от того, как они показаны. XAML становится тупым: так я представляю данные. Все бизнес-правила о том, как все работает, написаны на C # / sql, как ни на чем более выразительном (по крайней мере, IMO).

0 голосов
/ 18 сентября 2018

Вы можете привязать только к свойствам зависимости в вашем UserControl, нет никакого способа (afaik) для доступа к элементам XAML внутри вашего UserControl таким образом, поэтому вам нужно определить новое свойство Dependency в вашем UserControl, а затемпривязать к ней видимость вашей кнопки.

Если вы создаете UserControl, который должен предоставлять информацию «внешнему миру XAML», это то, как вы должны сделать это, по моему мнению.

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 к этому свойству, но так как DataContext из UserControl наследуется от родительского, он не будет работать сразу после установки.

Вы можете либо установить для себя DataContext DockPanel внутри вашего UserControl (НЕ меняйте UserControls DataContext), либо вы можете просто дать свой UserControl имя и использоватьElementName в привязке вашего RadioButton:

Давайте рассмотрим последний метод, поскольку он более понятен.

UserControl1.xaml

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

Я связываюсьОт RadioButton до IsRb1Checked напрямую, я не знаю, что такое SomeProperty в вашем примере, но вы можете создать свойство-обертку, которое устанавливает оба логических значения, или даже лучше использовать событие Checked для переключения IsRb1Checked.

Затем в вашем Window не забудьте использовать встроенный 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, что предотвратит повторное использование.Лучший способ - показать свойство зависимостей.

0 голосов
/ 17 сентября 2018

Предположение: свойство IsChecked имеет тип Boolean.Кнопка Visibility принимает значение либо Visible, Collapsed or Hidden.Чтобы приложение понимало, что нужно делать, когда значение равно true или false, вам необходим преобразователь логического значения в видимость.

Создайте ресурс, как показано ниже.

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

Обновите Visiblity кнопки, как показано ниже.

<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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...