DataTemplate 中的可见性绑定问题

Problems with Visibility Binding in DataTemplate

我不知道为什么,但我的可见性绑定并非仅在 DataTemplate 中起作用。我忘了什么吗? 编辑:所有绑定(除了这一个完美工作) 这就是结构。

<Window>
<Grid>
<Grid>
<Grid Grid.Row="5">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>                
                  <ItemsControl x:Name="Targets" Margin="0,4,0,4">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid Margin="0,5,0,5">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto" />
                                    <RowDefinition Height="Auto" />
                                </Grid.RowDefinitions>

                                <TextBox TextWrapping="Wrap" Foreground="{Binding Foreground, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Address, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Tag="{Binding}" PreviewKeyDown="ChangeLocationAddress" PreviewGotKeyboardFocus="TxtGotKeyboardFocusHandler" LostKeyboardFocus="ChangeLocationAddress" />
                                <Button Margin="2,0,0,0" Grid.Column="1" Content=" ↑ " Click="MoveLocationUp" Visibility="Visible" /> 
                                <Button Margin="2,0,0,0" Grid.Column="2" Content=" ↓ "  Click="MoveLocationDown" Visibility="{Binding Path = UpDownButtonVisibility, UpdateSourceTrigger=PropertyChanged}"/>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
           <Button x:Name="btnNewAddress" Grid.Row="1" Content="Neues Ziel hinzufügen" Margin="0,4,0,4" Visibility="{Binding Path=TargetButtonVisibility}"/>
        </Grid>
</Grid></Grid></Grid></Window>

代码隐藏:

public MapView(){
 this.DataContext = this.ViewModel = new MapVM();
 this.InitializeComponent();
 this.Targest.Itemssource = this.ViewModel.ToLocations;
}

视图模型:

public MapVM()
        {   this.UpDownButtonVisibility = Visibility.Collapsed;
            this.TargetButtonVisibility = Visibility.Collapsed;
        }
 private Visibility _UpDownButtonVisibility;
    /// <summary>
    /// Property Visibility für "↓" und "↑"
    /// </summary>
    public Visibility UpDownButtonVisibility
    {
        get { return _UpDownButtonVisibility; }
        set
        {
            this._UpDownButtonVisibility = value;
            NotifyPropertyChanged("UpDownButtonVisibility");
        }
    }
public Visibility TargetButtonVisibility { get; set; }

编辑: 程序输出: BindingExpression 路径错误:在 'object' ''Location' (HashCode=-794088449)' 上找不到 'UpDownButtonVisibility' 属性。 BindingExpression:Path=UpDownButtonVisibility; DataItem='Location' (哈希码=-794088449);目标元素是 'Button' (Name='');目标 属性 是 'Visibility'(类型 'Visibility')1.10s

有什么建议吗?

将字符串更改为可见性

public Visibility UpDownButtonVisibility { get; set; }
this.UpDownButtonVisibility = Visibility.Collapsed;

添加 INPC 并绑定到视图模型。

这是工作示例:

XAML

<Window x:Class="ItemsControlDataTemplate.MainWindow"
            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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:ItemsControlDataTemplate"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <ItemsControl x:Name="Targets" Margin="0,4,0,4" ItemsSource="{Binding Items}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="0,5,0,5">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>

                        <TextBox TextWrapping="Wrap" Foreground="{Binding Foreground, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Address, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" Tag="{Binding}" />
                        <Button Margin="2,0,0,0" Grid.Column="1" Content=" ↑ " Visibility="Visible" />
                        <Button Margin="2,0,0,0" Grid.Column="2" Content=" ↓ "   Visibility="{Binding Path=UpDownButtonVisibility}"/>

                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

    </Grid>
</Window>

C#

class MainWindowViewModel : INotifyPropertyChanged
{
    ObservableCollection<MapVM> _items = new ObservableCollection<MapVM>();

    public ObservableCollection<MapVM> Items { get { return _items; } }


    public MainWindowViewModel()
    {
        Items.Add(new MapVM() { UpDownButtonVisibility = Visibility.Visible, Address = "1111111" });
        Items.Add(new MapVM() { UpDownButtonVisibility = Visibility.Collapsed, Address = "222222" });
        Items.Add(new MapVM() { UpDownButtonVisibility = Visibility.Visible, Address = "33333333" });
    }

    public event PropertyChangedEventHandler PropertyChanged;

}




class MapVM : INotifyPropertyChanged
{

    public MapVM()
    {
        this.UpDownButtonVisibility = Visibility.Collapsed;
        this.TargetButtonVisibility = Visibility.Collapsed;
    }

    private Visibility _upDownButtonVisibility;
    public Visibility UpDownButtonVisibility
    {
        get { return _upDownButtonVisibility; }
        set
        {
            _upDownButtonVisibility = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(UpDownButtonVisibility)));
        }
    }


    private Visibility _targetButtonVisibility;
    public Visibility TargetButtonVisibility
    {
        get { return _targetButtonVisibility; }
        set
        {
            _targetButtonVisibility = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TargetButtonVisibility)));
        }
    }

    private string _address;
    public string Address
    {
        get { return _address; }
        set
        {
            _address = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Address)));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

我在您的代码中找不到 PropertyChanged 事件处理程序和对它的调用。将 INotifyPropertyChanged 添加到您的 DataContext 对象,它应该可以工作

我个人会将可见性建模为布尔值,并使用 WPF 附带的 BooleasnToVisibility 转换器。

您的 TargetButtonVisibility 绑定的 DataContext 是您的主要 MapVM。这工作正常。

你的 DataTemplate 中的 DataContext 不是 MapVM,它是 正在显示的项目吗模板。

由于您没有为您的 ItemsControl 提供任何 ItemsSource 绑定,我们无法知道这到底是什么。

此外,正如 unkreativ 指出的那样,不要在您的 VM 中使用可见性,因为这是与视图相关的类型。请改用 bool 并调用 属性 IsUpDownButtonVisible 或类似方法。

编辑:假设你确实想要绑定到你的单身MapVM,你可以使用RelativeSource 找到父级 ItemsControl:

<Button Margin="2,0,0,0" 
        Grid.Column="2" 
        Content=" ↓ "  
        Click="MoveLocationDown" 
        Visibility="{Binding DataContext.UpDownButtonVisibility,
                             RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}"/>

但是,由于您已经为 ItemsControl (Targets) 命名,您可以简单地通过名称引用它:

<Button Margin="2,0,0,0" 
        Grid.Column="2" 
        Content=" ↓ "  
        Click="MoveLocationDown" 
        Visibility="{Binding DataContext.UpDownButtonVisibility,
                             ElementName=Targets}"/>