Luffy
Luffy

Reputation: 677

Wpf binding button with listview.Item

Hi i want to bind button with other listView.Item. What i want is to have something like we have on stackoverflow. But i have problem with having increasing/decreasing value. I have event Click but i dont knew how to get corresponding item on list and increase/decrease value. List view. Concept model

<DataTemplate>
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Horizontal">
            <Label Width="706" Height="75" Content="{Binding feedback}"/>
            <StackPanel Orientation="Vertical">
                <Button Name="buttonUp" Content="^" Command="{Binding upVoteCommand}" />
                <Label HorizontalContentAlignment="Center" Width="50" Content="{Binding grade}"/>
                <Button Name="buttonDown" Content="v" Command="{Binding upVoteCommand}"/>
            </StackPanel>
        </StackPanel>
        <Label>-</Label>
    </StackPanel >

EDIT

class A {
    public string feedback {
        get;
        set;
    }
    public int grade {
        get;
        set;
    }

    private ICommand _upVoteCommand;
    private ICommand _downVoteCommand;
    public ICommand upVoteCommand {
        get {
            return _upVoteCommand;
        }
        set {
            _upVoteCommand = value;
        }
    }
    public ICommand downVoteCommand {
        get {
            return _downVoteCommand;
        }
        set {
            _downVoteCommand = value;
        }
    }
}

EDIT I used this button.Commmand but still it not working. I dont knew what to do with this commands.

Upvotes: 0

Views: 1926

Answers (2)

dkozl
dkozl

Reputation: 33384

First you'll need your implementation of ICommand so you can bind commands from view model to controls, something like this:

public class RelayCommand : ICommand
{
  private readonly Action<object> _execute;
  private readonly Predicate<object> _canExecute;

  public RelayCommand(Action<object> execute) : this(execute, null) { }

  public RelayCommand(Action<object> execute, Predicate<object> canExecute)
  {
      if (execute == null) throw new ArgumentNullException("execute");
      _execute = execute; 
      _canExecute = canExecute;
  }

  public bool CanExecute(object parameter)
  {
      return _canExecute == null ? true : _canExecute(parameter);
  }

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

  public void Execute(object parameter) { _execute(parameter); }
}

then in you class, where you publish Feedback, you'll need to publish 2 new RelayCommand for up/down vote that will modify Feedback property accordingly. Below you can find my class that I used for tests:

public class MyClass : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  private void OnPropertyChanged(string propertyName)
  {
      if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }

  private int _feedback = 0;

  public int Feedback
  {
      get { return _feedback; }
      set
      {
          if (_feedback == value) return;
          _feedback = value;
          OnPropertyChanged("Feedback");
      }
  }

  private RelayCommand _upVoteCmd;

  public ICommand UpVoteCmd
  {
      get
      {
          if (_upVoteCmd == null) _upVoteCmd = new RelayCommand(o => Feedback += 1);
          return _upVoteCmd;
      }
  }

  private RelayCommand _downVoteCmd;

  public ICommand DownVoteCmd
  {
      get
      {
          if (_downVoteCmd == null) _downVoteCmd = new RelayCommand(o => Feedback -= 1);
          return _downVoteCmd;
      }
  }

}

and then you bind your new commands in XAML like this:

<Button Content="+" Command="{Binding Path=UpVoteCmd}"/>
<TextBlock Text="{Binding Path=Feedback}"/>            
<Button Content="-" Command="{Binding Path=DownVoteCmd}"/>

Upvotes: 2

dowhilefor
dowhilefor

Reputation: 11051

RoutedEvents don't work so easily with DataTemplates, because you don't have a code behind where your event code could be placed. While there are ways to do that, you can just use Commands to do the same. In the view model for each item (i just assume you use MVVM) create properties called UpVoteCommand and DownVoteCommand of type ICommand, DelegateCommands are quiet handy for this. Bind them to the Command property and remove the Click handler in your DataTemplate.

[EDIT]

Small example of a possible Viewmodel for one entry in the list, which can be up or downvoted.

class MyEntryViewModel : INotifyPropertyChanged
{
    public MyEntryViewModel()
    {
        UpVoteCommand = new DelegateCommand(OnUpVoteCommand);
    }
    public int Votes 
    {
        get {return mVotes;}
        set {mVotes = value; RaiseProperty("Votes");}
    }

    public ICommand UpVoteCommand 
    {
        get; private set;
    }

    void OnUpVoteCommand(object aParameter)
    {
        Votes++;
    }
}

i left the implementation of INotifyPropertyChanged and the down vote command for sake of simplicity.

Upvotes: 1

Related Questions