Я пытался сделать это, используя привязку с именем элемента вместо x:Bind, но в WinUI это просто не работает. Может ли кто-нибудь показать рабочий пример, где вы, например, привязываете кнопку внутри представления списка к предку и свойству в коде файла?
То, что я пробовал упрощенно, это:
<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>
Давайте сделаем это просто. Допустим, у вас есть логическое значение в коде, которое определяет, должна ли кнопка быть видимой. Кнопка находится внутри представления списка, а источник представления списка привязан к коллекции в модели представления. Следовательно, вы должны привязаться к предку. Я попытался назвать пользовательский компонент, а затем использовать имя элемента для ссылки на него, но он остается видимым, несмотря ни на что. Разве это не правильный подход?
Вот рабочий пример, основанный на вашем комментарии:
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();
}
Шеллвиевмодел.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;
}
}
Shell
названа x:Name для доступа к ней изнутри ItemTemplate
.Это очень похоже на то, что я сделал на самом деле. Один вопрос: нужно ли привязку по-прежнему наблюдать?
Вы имеете в виду свойство ShowButton? Тогда да, если ожидается изменение значения. Вам нужно реализовать INotifyPropertyChanged
, но в этом вам поможет CommunityToolkit.Mvvm.
Кроме того, в моем случае свойство находится не в модели, а в файле .xaml.cs.
Оно никогда не меняется. Его просто нужно прочитать один раз во время запуска.
Вообще говоря, это должно быть во ViewModel. В противном случае вам придется реализовать INotifyPropertyChanged
самостоятельно, без помощи CommunityToolkit.Mvvm. Если вам нужно получить к нему доступ из кода программной части (*.xaml.cs), вы можете просто сделать ViewModel.ShowButtons
.
Если он никогда не изменится, тогда он может оказаться в коде программной части.
Это возможно, но вам нужно быть более конкретным, чтобы показать вам рабочий пример. Что происходит при нажатии кнопки? Нужно ли привязывать кнопку к команде в ViewModel или просто к обработчику событий щелчка? Что привязано к свойству в коде программной части?