使用MVVM模式将项添加到集合

时间:2015-02-17 14:27:46

标签: c# wpf xaml mvvm

我正在从附加到每个项目的命令中访问ObservableCollection(这是我的ItemsSource)。

我正在尝试制作两个列表,一个包含所有对象,第二个包含用户选择的对象。

这是我的观点模型。

class ViewModel : VMBase
{
    private ObservableCollection<Card> _cardsCollection;
    public ObservableCollection<Card> CardsCollection
    {
        get { return _cardsCollection; }
        set { _cardsCollection = value; }
    }

    static private ObservableCollection<Card> _pickedCards;
    static public ObservableCollection<Card> PickedCards
    {
        get { return _pickedCards; }
        set { _pickedCards = value;
              NotifyPropertyChanged("PickedCards");
            }
    }
}
class Card : VMBase
{
    public string Name { get; set; }
    public Card(string name, int cost, CardType type, CardRarity rarity)
    {
        this.Name = name;
        this.BackgroundImage = String.Format("/Images/Cards/{0}.png", name);

        this.PickCardCommand = new MvvmCommand();
        this.PickCardCommand.CanExecuteFunc = obj => true;
        this.PickCardCommand.ExecuteFunction = PickCard;
    }
    public MvvmCommand PickCardCommand { get; set; }
    public void PickCard(object parameter)
    {
        PickedCards.Add(currentCard); 
        //Above Does not work, not accessible
        CreateDeckModel.PickedCards.Add(currentCard);
        //Above does work but only if Collection is static
        //but if collection is static I am unable to call NotifyPropertyChanged()
    }
}

这是我的带有绑定的XAML文件

<GridView Grid.Row="1" ItemsSource="{Binding CardsCollection, Mode=TwoWay}">
     <GridView.ItemTemplate>
         <DataTemplate>
             <Grid>
                  <Button Height="258" Width="180" Content="{Binding}" Margin="0,0,0,0" 
                          Command="{Binding PickCardCommand}" CommandParameter="{Binding}">
                      <Button.Template>
                          <ControlTemplate>
                              <StackPanel Orientation="Vertical">
                                  <Border BorderThickness="2" BorderBrush="White" Height="258" Width="180">
                                      <Border.Background>
                                          <ImageBrush ImageSource="{Binding BackgroundImage}" />
                                      </Border.Background>
                                   </Border>
                              </StackPanel>
                          </ControlTemplate>
                       </Button.Template>
                   </Button>
               </Grid>
           </DataTemplate>
       </GridView.ItemTemplate>
   </GridView>

这是我的MvvmCommand类

class MvvmCommand : ICommand
{
    public Predicate<object> CanExecuteFunc { get; set; }
    public Action<object> ExecuteFunction { get; set; }
    public void Execute(object parameter)
    {
        ExecuteFunction(parameter);
    }

    public event EventHandler CanExecuteChanged;
    public bool CanExecute(object parameter)
    {
        return CanExecuteFunc(parameter);
    }
}

}

有没有办法从Item或DataContext访问ItemsSource,或者为ViewModel Class访问make命令?

3 个答案:

答案 0 :(得分:2)

您可以通过将xaml文件中的按钮更改为以下命令,将Command指向ViewModel类:

<Button Height="258" Width="180" Content="{Binding}" Margin="0,0,0,0" Command="{Binding DataContext.PickCardCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type vw:ViewClass}}}" CommandParameter="{Binding}">

在RelativeSource绑定中,您需要更改以下内容:

vw 是View的命名空间,必须使用xaml文件中的其他命名空间声明。

ViewClass 是您班级的名称。

然后你显然需要将Command从Card类移到ViewModel类。

Windows Phone

<GridView x:Name="myGridView" Grid.Row="1" ItemsSource="{Binding CardsCollection, Mode=TwoWay}">
     <GridView.ItemTemplate>
         <DataTemplate>
             <Grid>
                  <Button Height="258" Width="180" Content="{Binding}" Margin="0,0,0,0" 
                          Command="{Binding ElementName=myGridView,
                   Path=DataContext.PickCardCommand}" CommandParameter="{Binding}">
                      <Button.Template>
                          <ControlTemplate>
                              <StackPanel Orientation="Vertical">
                                  <Border BorderThickness="2" BorderBrush="White" Height="258" Width="180">
                                      <Border.Background>
                                          <ImageBrush ImageSource="{Binding BackgroundImage}" />
                                      </Border.Background>
                                   </Border>
                              </StackPanel>
                          </ControlTemplate>
                       </Button.Template>
                   </Button>
               </Grid>
           </DataTemplate>
       </GridView.ItemTemplate>
   </GridView>

您将看到我现在已经命名了GridView,然后在绑定中使用GridView的名称作为ElementName。我相信这应该有用。

答案 1 :(得分:0)

您可以在创建时将Add PickedCards Card方法传递给class Card : VMBase { private readonly Action<Card> _addCard; public Card(..., Action<Card> addCard) { ... _addCard = addCard; this.PickCardCommand = new MvvmCommand(); this.PickCardCommand.CanExecuteFunc = obj => true; this.PickCardCommand.ExecuteFunction = PickCard; } public MvvmCommand PickCardCommand { get; set; } public void PickCard(object parameter) { _addCard(this); } }

var card = new Card(..., ..., ..., ..., PickedCards.Add)

然后当你创建卡片时:

{{1}}

答案 2 :(得分:-1)

您可以将集合绑定到Command参数。命令参数当前绑定到Item DataSource而不是集合

CommandParameter="{Binding}"

而是使用RelativeBinding并绑定到grid

的itemSource