2015-01-08 21 views
6

Tôi có một vấn đề với các ràng buộc cho DataTemplate dựa trên định nghĩa DataType trong ItemsControl, khi tôi muốn để ràng buộc để điều khiển người dùng tùy chỉnh của tôi.Ràng buộc để điều khiển tùy chỉnh bên trong DataTemplate cho ItemsControl

Đối với mục đích trình diễn, tôi đã tạo đơn giản Lớp Item dụ, nơi tôi có bộ sưu tập các mặt hàng như thế này:

public class Item 
{ 
    public string ItemNameToBeSureWhatPropertyIsBound { get; set; } 
} 

Trong tôi ViewModel tôi tạo bộ sưu tập như vậy, và vạch trần nó (với một mục để so sánh riêng):

public class MainWindowViewModel : INotifyPropertyChanged 
{ 
    private ObservableCollection<Item> _items; 
    private Item _exampleItem; 

    public MainWindowViewModel() 
    { 
     Items = new ObservableCollection<Item>(new[] { new Item { ItemNameToBeSureWhatPropertyIsBound = "Me" }, new Item { ItemNameToBeSureWhatPropertyIsBound = "MySelf" }, new Item { ItemNameToBeSureWhatPropertyIsBound = "Ich" }, }); 
     ExampleItem = Items.LastOrDefault(); 
    } 

    public ObservableCollection<Item> Items 
    { 
     get { return _items; } 
     set { _items = value; OnPropertyChanged(); } 
    } 

    public Item ExampleItem 
    { 
     get { return _exampleItem; } 
     set { _exampleItem = value; OnPropertyChanged();} 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

My điều khiển người dùng tùy chỉnh được định nghĩa như thế này:

<UserControl x:Class="WpfDataTemplate.ItemRowUserControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="40" d:DesignWidth="300" 
     x:Name="ItemRowControl" DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}"> 

    <Grid Background="Yellow" Height="40"> 
     <TextBlock Text="{Binding ItemName}" Foreground="Black"/> 
    </Grid> 
</UserControl> 

... và nó có một DependencyProperty trong mã sau:

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

    public static readonly DependencyProperty ItemNameProperty = DependencyProperty.Register(
     "ItemName", typeof (string), typeof (ItemRowUserControl), new PropertyMetadata(default(string))); 

    public string ItemName 
    { 
     get { return (string) GetValue(ItemNameProperty); } 
     set { SetValue(ItemNameProperty, value); } 
    } 
} 

Vấn đề là, khi tôi cố gắng liên kết với tài sản của Item trong DataTemplate cho ItemsControl, mà tôi đang thực hiện trong MainWindow như thế này (lưu ý: Tôi có bộ chuyển đổi giả cho mục đích gỡ lỗi, trả lại giá trị và không có gì khác):

<Window.DataContext> 
    <my:MainWindowViewModel /> 
</Window.DataContext> 
<Window.Resources> 
    <my:MyDummyConverter x:Key="MyDummyConverter" /> 
</Window.Resources> 

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition Height="50" /> 
    </Grid.RowDefinitions> 

    <ItemsControl Name="ItemsControl" ItemsSource="{Binding Items}" Grid.Row="0" Background="Red"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 

     <ItemsControl.ItemTemplate> 
      <DataTemplate DataType="{x:Type my:Item}"> 
       <my:ItemRowUserControl ItemName="{Binding ItemNameToBeSureWhatPropertyIsBound, Converter={StaticResource MyDummyConverter}}" /> 
       <!--<Grid Background="Pink"> 
        <TextBlock Text="{Binding ItemNameToBeSureWhatPropertyIsBound, Converter={StaticResource MyDummyConverter}}" Foreground="Black" Height="30" /> 
       </Grid>--> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

    <Grid Grid.Row="1"> 
     <my:ItemRowUserControl ItemName="{Binding DataContext.ExampleItem.ItemNameToBeSureWhatPropertyIsBound, ElementName=MyWindow, Converter={StaticResource MyDummyConverter}}" /> 
    </Grid> 
</Grid> 

Bây giờ, trong trường hợp tôi liên kết với ItemRowUserControl tùy chỉnh của tôi, giá trị tôi nhận được vào bộ chuyển đổi (và tôi thấy điều tương tự trong Debug Output) chính là ItemRowUserControl. Nhưng nếu tôi liên kết với nhận xét ra mã, mọi thứ hoạt động tốt. Tại sao điều đó, và làm thế nào tôi có thể có điều khiển tùy chỉnh cho DataTemplate để các ràng buộc (được cung cấp bởi intellisense) sẽ làm việc? Về phía lưu ý: ràng buộc với ItemRowUserControl của tôi trong hàng lưới 1 (ở phía dưới) hoạt động tốt, vì vậy tôi đoán kiểm soát được thiết lập để làm việc như mong đợi?

Trả lời

5

Vấn đề là bạn một cách rõ ràng thiết lập DataContext của usercontrol của bạn với bản thân:

DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}} 

Di chuyển nhượng đó và viết ItemName ràng buộc như thế này:

<TextBlock Text="{Binding ItemName, 
    RelativeSource={RelativeSource AncestorType=UserControl}}"/> 

hay như thế này

<TextBlock Text="{Binding ItemName, ElementName=ItemRowControl}"/> 
+0

Cảm ơn bạn, điều này hoạt động như mong đợi. Bạn có thể giải thích phần RelativeSource của sự ràng buộc được không? Ràng buộc với ElementName trong câu trả lời của bạn, có ý nghĩa với tôi. Cảm ơn một lần nữa. –

+1

Vui lòng tham khảo [tài liệu trực tuyến] (http://msdn.microsoft.com/en-us/library/system.windows.data.binding.relativesource.aspx) trên MSDN. Trong cả hai trường hợp, cá thể UserControl được đặt làm đối tượng nguồn của liên kết. – Clemens

+1

@JanezLukan có nghĩa là tương đối tra cứu trong cây điều khiển cho đến khi nó tìm thấy điều khiển kiểu 'UserControl' và tra cứu sẽ trở lên vì nó nói 'AncestorType' –

Các vấn đề liên quan