2015-10-03 27 views
-1

我有2個任務。綁定usercontrol裏面itemcontrol

  1. 將一個用戶控件添加到父窗口。
  2. 將一個usercontrol的集合添加到父窗口。

我有問題完成任務2有關的數據綁定和命令綁定。

如果有人知道如何做任務2,請添加一些代碼。 這是我的兩個任務的實施,以防有人想修復它..:

我有一個名爲「書」的用戶控件包含3個文本塊和一個按鈕。 userControl具有我的書籍模型和按鈕命令的dependecyProperty。

Book.xaml

<UserControl x:Name="MyBookControl" 
    <Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, 
    AncestorType={x:Type Controls:BookControl}}, Path=TheBook}"> 
    <Label Grid.Row="0">Title</Label> 
     <Label Grid.Row="1">Author</Label> 
     <Label Grid.Row="2">Description</Label> 

     <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Title}"/> 
     <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Author}"/> 
     <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Description}"/> 
    <Button Grid.Row="3" Command="{Binding 
    SomeCommand,ElementName=MyBookControl}" Content="Save" /> 
    </Grid> 

Book.xaml.cs

public partial class BookControl : UserControl 
    { 
     public BookControl() 
     { 
      InitializeComponent(); 
     } 

     public BookModel TheBook 
     { 
      get { return (BookModel)GetValue(TheBookProperty); } 
      set { SetValue(TheBookProperty, value); } 
     } 
     public static DependencyProperty TheBookProperty = DependencyProperty.Register("TheBook", typeof(BookModel), typeof(BookControl)); 

     public ICommand SomeCommand 
     { 
      get { return (ICommand)GetValue(SomeCommandProperty); } 
      set { SetValue(SomeCommandProperty, value); } 
     } 

     public static readonly DependencyProperty SomeCommandProperty = 
      DependencyProperty.Register("SomeCommand", typeof(ICommand), typeof(BookControl), new UIPropertyMetadata(null)); 
    } 

BookModel.cs

public class BookModel 
    { 
     public string Title { get; set; } 
     public string Author { get; set; } 
     public string Description { get; set; } 
    } 

爲了完成任務1我創建了一個窗口: BookWindow

<Window 
     DataContext="{Binding Source={StaticResource Locator}, Path=Main}" 
> 
<StackPanel> 
<Controls:BookControl TheBook="{Binding Book}" SomeCommand="{Binding 
    SaveCommand}" /> 
    </StackPanel> 

BookViewModel.cs

public BookModel Book { get; set; } 
public MainViewModel() 
     { 
      Book = new BookModel{Title = "A Book", Author = "Some Author", 
      Description = "Its a really good book!"}; 
     } 

    private ActionCommand _SaveCommand; 
      public ICommand SaveCommand 
      { 
       get 
       { 
        if (_SaveCommand == null) 
        { 
         _SaveCommand = new ActionCommand(OnSaveCommand, CanSaveCommand); 
        } 
        return _SaveCommand; 
       } 
      } 
      protected virtual void OnSaveCommand() 
      { 
       MessageBox.Show("save clicked"); 
      } 

      protected virtual bool CanSaveCommand() 
      { 
       return true; 
      } 

大,任務完成1 https://onedrive.live.com/redir?resid=3A8F69A0FB413FA4!116&authkey=!AHiyrfEnBr2a-rM&v=3&ithint=photo%2cpng

現在,試圖完成的任務2:

ContainerWindow:

<Window 
    DataContext="{Binding Source={StaticResource Locator}, Path=Container}" 
     > 
    <StackPanel> 
     <ItemsControl ItemsSource="{Binding Books}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Vertical" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <Controls:BookControl /> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 

     </ItemsControl> 
    </StackPanel> 

ContainerViewModel.cs:

private ObservableCollection<BookModel> books; 
     public ObservableCollection<BookModel> Books 
     { 
      get 
      { 
       if (books == null) 
       { 
        // Not yet created. 
        // Create it. 
        books = new ObservableCollection<BookModel>(); 
       } 

       return books; 
      } 
     } 

     public ContainerViewModel() 
     { 
      BookModel book1 = new BookModel { Title = "A Book 2", Author = "Some Author", Description = "Its a really good book!" }; 
      BookModel book2 = new BookModel { Title = "A Book 3", Author = "Some Author", Description = "Its a really good book!" }; 
      Books.Add(book1); 
      Books.Add(book2); 
     } 

綁定失敗,按鈕「保存」停止重新編碼。 https://onedrive.live.com/redir?resid=3A8F69A0FB413FA4!121&authkey=!AKnyQk6Ge_9QHug&v=3&ithint=photo%2cpng

那麼,這是怎麼回事?爲什麼綁定失敗,爲什麼按鈕「保存」不起作用?

回答

1

您沒有在列表示例中設置您的DependencyProperties。

<DataTemplate> 
     <Controls:BookControl /> 
</DataTemplate> 

看看你在非列表版本中是如何做到的。

<Controls:BookControl TheBook="{Binding Book}" SomeCommand="{Binding 
SaveCommand}" /> 

話雖這麼說,你並不需要在所有的DependencyProperties,該用戶控件將在圖書列表繼承DataContext的每個「書」作爲ItemsControl的創建它們。你只需要不在網格上設置DataContext。

然後您的按鈕可以只綁定到BookViewModel命令屬性。

<Button Grid.Row="3" Command="{Binding SaveCommand}" Content="Save" /> 

如果您的問題不知道繼承DataContext的可用範圍,可以這樣做來獲得設計時支持。

d:DataContext="{d:DesignInstance Type=local:BookViewModel, 
              IsDesignTimeCreatable=False}" 

只要確保以下內容在文件的某個位置定義,通常是默認情況下。

xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 

更新

所以我錯過了第二個問題,應該有實際發射了Visual Studio中。問題是你的命令在MainViewModel.cs中。也就是說,我們的UserControl已經繼承了每個Book對象的DataContext。簡而言之,該按鈕正在查找Book對象內部的命令。

我打算假設你有一個保存命令,你將編輯Book對象。所以讓我們藉此機會繼續製作一個ViewModel。我將把save命令移動到那裏,以便保存始終可用於BookViewModel。可能有很好的理由讓save命令在其他地方,但爲了簡單起見,我們將它放在ViewModel中。

此外,我不確定您是否在任何地方實施了INotifyPropertyChanged,因爲您的MainViewModel和ContainerViewModel未顯示使用了該方法。如果您不這樣做,我強烈建議您退後一步,查看ViewModel的實現或MVVM框架。

BookViewModel.cs

public class BookViewModel 
{ 
    private readonly BookModel book; 

    public BookViewModel(BookModel book) 
    { 
     this.book = book; 
     SaveCommand = new ActionCommand(OnSaveCommand, CanSaveCommand); 
    } 

    public ICommand SaveCommand { get; private set; } 

    public string Title 
    { 
     get { return book.Title; } 
     set { book.Title = value; } 
    } 

    public string Author 
    { 
     get { return book.Author; } 
     set { book.Author = value; } 
    } 

    public string Description 
    { 
     get { return book.Description; } 
     set { book.Description = value; } 
    } 

    protected virtual void OnSaveCommand() 
    { 
     MessageBox.Show("Save clicked for the book '" + Title + "'."); 
    } 

    protected virtual bool CanSaveCommand() 
    { 
     return true; 
    } 
} 

這是一個什麼樣你可能會想要做一個非常簡單的例子。我想保持簡單,不要脫離這個例子,你可能希望至少做一些空的檢查。

上述規定,你不應該改變你的用戶控件的任何,我不得不添加的行和列的定義,但我結束了以下內容:

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="Auto" /> 
     <ColumnDefinition Width="Auto" /> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Label Grid.Row="0" Grid.Column="0">Title</Label> 
    <TextBlock Grid.Row="0" 
       Grid.Column="1" 
       Text="{Binding Title}" /> 
    <Label Grid.Row="1" Grid.Column="0">Author</Label> 
    <TextBlock Grid.Row="1" 
       Grid.Column="1" 
       Text="{Binding Author}" /> 
    <Label Grid.Row="2" Grid.Column="0">Description</Label> 
    <TextBlock Grid.Row="2" 
       Grid.Column="1" 
       Text="{Binding Description}" /> 
    <Button Grid.Row="3" 
      Grid.Column="0" 
      Command="{Binding SaveCommand}" 
      Content="Save" /> 
</Grid> 

希望你注意到我們BookViewModel的構造函數接受一本書,所以這意味着我們需要更改我們的ContainerViewModel以容納適當的集合並正確創建它們。

public class ContainerViewModel 
{ 
    private ObservableCollection<BookViewModel> books; 

    public ContainerViewModel() 
    { 
     Books.Add(
      new BookViewModel(new BookModel 
      { 
       Title = "A Book 2", 
       Author = "Some Author", 
       Description = "Its a really good book!" 
      })); 
     Books.Add(
      new BookViewModel(new BookModel 
      { 
       Title = "A Book 3", 
       Author = "Some Author", 
       Description = "Its a really good book!" 
      })); 
    } 

    public ObservableCollection<BookViewModel> Books 
    { 
     get 
     { 
      if (books == null) 
      { 
       // Not yet created. 
       // Create it. 
       books = new ObservableCollection<BookViewModel>(); 
      } 

      return books; 
     } 
    } 
} 

這一切,你的ItemsControl可以簡單如下:

<ItemsControl ItemsSource="{Binding Path=Books}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <local:MyBookControl /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 
+0

嗨,感謝您的回答。 我按照你的建議做了(從Book UserControl中刪除依賴項屬性,在按鈕內部分配命令指向bookviewmodel)。數據在我的問題中遇到的兩個任務中按預期進行綁定,但是在列表版本中 - 每個按鈕的命令都不起作用。你能幫助解決這個問題嗎? – Liran

+0

我看到另一個問題,當我到達一臺計算機時,我會提供一個解決方案。我應該測試過我發佈的內容,我的歉意。 –

+0

已更新,以解決第二個問題。希望能夠幫助你並使你運轉起來。 –