0
votes

I don't know why but my Visibility Binding isn't working ONLY in the DataTemplate. Did I forget something? Edit: All Bindings (except for this one work perfectly) Thats the structure.

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

Codebehind:

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

ViewModel:

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

EDIT: Program Output: BindingExpression path error: 'UpDownButtonVisibility' property not found on 'object' ''Location' (HashCode=-794088449)'. BindingExpression:Path=UpDownButtonVisibility; DataItem='Location' (HashCode=-794088449); target element is 'Button' (Name=''); target property is 'Visibility' (type 'Visibility') 1.10s

Any suggestions?

3
How is TargetButtonVisibility declared? Check into that for why the other isn't working. My first guess is an issue with you not notifying the UI of changes for UpDownButtonVisibility, but without seeing the other one, I'm guessing. - Khale_Kitha

3 Answers

0
votes

The DataContext of your TargetButtonVisibility binding is your main MapVM. This works ok.

The DataContext within your DataTemplate is not MapVM, is it the item being displayed by the template.

Since you have not supplied any ItemsSource binding on your ItemsControl we have no way of knowing what this actually is.

Also, as unkreativ points out, do not use Visibility in your VM, since this is a view related type. Use bool instead and call the property IsUpDownButtonVisible or similar.

EDIT: Assuming you do actually want to bind to your single MapVM, you could use a RelativeSource to find the parent 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}}"/>

However, since you've already named your ItemsControl (Targets), you can simply refer to it by name:

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

I cannot find a PropertyChanged event handler and a call to it in your code. Add the INotifyPropertyChanged to your DataContext object and it should work

Personally I would model the visibility as a bool and use the BooleasnToVisibility Converter that comes with WPF.

1
votes

Change string to Visibility

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

Add INPC and binding to a View model.

Here is working sample:

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