xamlwinui-3winui

How to bind to ancestor property in code behind


I have tried to do this using binding with element name instead of x:Bind, but it simply doesn’t work in winui. Can someone show a working example where you for example bind a button inside a list view to the ancestor and to a property in the code behind file?

What I have tried simplified is:

  <ListView
      x:Name="View"
      ItemsSource="{x:Bind Model.Objects, Mode=OneWay}"
      <ListView.ItemTemplate>
              <StackPanel Margin="8" Orientation="Horizontal">
                  <StackPanel Orientation="Vertical">            
                      <Button
                          x:Name="SomeButton
                          Visibility="{Binding Path=PropertyInCodeBehind, ElementName=View//or even the user control">
                      </Button>
                  </StackPanel>
              </StackPanel>
          </DataTemplate>
      </ListView.ItemTemplate>
  </ListView>

Solution

  • Here is a working example based on your comment:

    Shell.xaml

    <Page
        x:Class="WinUIApp5.Shell"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="using:WinUIApp5"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        x:Name="RootPage"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
        mc:Ignorable="d">
    
        <Page.Resources>
            <local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
        </Page.Resources>
    
        <Grid RowDefinitions="Auto,*">
            <ToggleSwitch
                Grid.Row="0"
                Header="Show Buttons"
                IsOn="{x:Bind ViewModel.ShowButtons, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <ListView
                Grid.Row="1"
                ItemsSource="{x:Bind ViewModel.Items}">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="x:String">
                        <Button
                            Content="{x:Bind}"
                            Visibility="{Binding ElementName=RootPage, Path=ViewModel.ShowButtons, Converter={StaticResource BoolToVisibilityConverter}}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    
    </Page>
    

    Shell.xaml.cs

    public sealed partial class Shell : Page
    {
        public Shell()
        {
            InitializeComponent();
        }
    
        public ShellViewModel ViewModel { get; } = new();
    }
    

    ShellViewModel.cs

    public partial class ShellViewModel : ObservableObject
    {
        [ObservableProperty]
        private ObservableCollection<string> _items =
            [
            "Item #1",
            "Item #2",
            "Item #3",
            ];
    
        [ObservableProperty]
        private bool _showButtons = false;
    }
    

    BoolToVisibilityConverter.cs

    public class BoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return (bool)value ? Visibility.Visible : Visibility.Collapsed;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return (Visibility)value == Visibility.Visible;
        }
    }
    

    Remarks