Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

The problem that I have is getting my button to work with the binding. I'm not sure what to set the DataContext. I am getting this error with my binding:

System.Windows.Data Error: 40 : BindingExpression path error: 'ClickMeCommand' property not found on 'object' ''Person' (HashCode=13029119)'. BindingExpression:Path=ClickMeCommand; DataItem='Person' (HashCode=13029119); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')

What I'm doing here is I have a ListView in XAML and I have a Grid View with three columns. One column stores Name from the Person object, the second column stores Date from the Person object, and the third column is the same for everything on the list, a button. When the button is clicked, I want to execute a command to remove the task from my observable collection and update the list. I know how to do that but I can't get the binding command for the button to work.

<ListView x:Name="List" HorizontalAlignment="Left" Margin="0,0,0,-2"` Width="292" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Height="Auto">
                    <ListView.ItemContainerStyle>
                        <Style TargetType="{x:Type ListViewItem}">
                            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.View>
                    <GridView>
                        <GridView.ColumnHeaderContainerStyle>
                            <Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="{x:Type GridViewColumnHeader}">
                                <Setter Property="IsHitTestVisible" Value="False"/>
                            </Style>
                        </GridView.ColumnHeaderContainerStyle>
                        <GridViewColumn x:Name="Column1" Header="Assignment" DisplayMemberBinding="{Binding Name}" Width="190"/>
                        <GridViewColumn x:Name="Column2" Header="Date" DisplayMemberBinding="{Binding Date}" Width="45"/>
                        <GridViewColumn Header="Edit" Width="35" CellTemplate="{StaticResource editColumnTemplate}">
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>


<Window.Resources>
        <DataTemplate x:Key="editColumnTemplate">
            <StackPanel Orientation="Horizontal">
                <Button x:Name="deleteButton" Content="X"  Command="{Binding Path=ClickMeCommand}" HorizontalAlignment="Stretch"/>
            </StackPanel>
        </DataTemplate>
</Window.Resources>

//

private class Person
        {
            public String Name { get; set; }
            public String Date { get; set; }

        }

In my code behind, I create a new tab and add a listview in it. Everytime I add a new person, it would add a line in the list with his/her name / date and a button on the third column.

 public MainWindow(){
     InitializeComponent();
     this.DataContext = new MainViewModel();
}
TabItem newItem = new TabItem();
ListView newList = new ListView();
ObservableCollection<TabItem> newSource = new ObservableCollection<TabItem>();
newList.ItemsSource = newSource;
TabControl.Items.Add(newItem);

That button is binded to the command ClickMeCommand as you can see from above. This is the class:

 public class MainViewModel
{
    public MainViewModel()
    {

    }

    private ICommand clickMeCommand;
    public ICommand ClickMeCommand
    {
        get
        {
            if (clickMeCommand == null)
                clickMeCommand = new RelayCommand(i => this.ClickMe(), null);
            return clickMeCommand;
        }
    }

    private void ClickMe()
    {
        MessageBox.Show("You Clicked Me");
    }
}    
public class RelayCommand : ICommand
{
    readonly Action<object> execute;
    readonly Predicate<object> canExecute;

    public RelayCommand(Action<object> executeDelegate, Predicate<object> canExecuteDelegate)
    {
        execute = executeDelegate;
        canExecute = canExecuteDelegate;
    }

    bool ICommand.CanExecute(object parameter)
    {
        return canExecute == null ? true : canExecute(parameter);
    }

    event EventHandler ICommand.CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    void ICommand.Execute(object parameter)
    {
        execute(parameter);
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
105 views
Welcome To Ask or Share your Answers For Others

1 Answer

You have defined the Button inside the DataTemplate of the ListView Item and it cannot access the command which in the DataContext of the Window, So you need to use the RelativeSource binding refer the below template code.

 <DataTemplate x:Key="editColumnTemplate">
        <StackPanel Orientation="Horizontal">
            <Button x:Name="deleteButton" Content="X"  Command="{Binding Path=DataContext.ClickMeCommand,
                      RelativeSource={RelativeSource Mode=FindAncestor,
                                                     AncestorType=Window}}" HorizontalAlignment="Stretch"/>
        </StackPanel>
    </DataTemplate>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...