2015-01-09 37 views
2

今天,我無法將值從父控件傳遞到列表中子控件的屬性。將非項目值傳遞給ItemTemplate中的屬性

我有一個自定義控件,我做了一個縮略圖複選框。基本上它只是一個複選框,用一些漂亮的邊框包裹圖像。這一切都裹成一個DLL和部署爲一個自定義的控制

如果我想使用該控件的一個實例,我可以這樣做這樣的...

<tcb:ThumbnailCheckBox IsChecked="True" 
         ImagePath="D:\Pictures\123.jpg" 
         CornerRadius="10" 
         Height="{Binding ThumbnailSize}" 
         Margin="10" /> 

代碼1 - 一次性使用

這很好用,並且很容易綁定到我的ViewModel上的ThumbnailSize,所以我可以改變控件中圖像的大小,但是我想要。

問題是,當我想擴大使用這個控件到列表中時,我遇到了一些問題。

首先,我樣式列表框控件,以滿足像這樣我的需求......

<Style TargetType="{x:Type ListBox}" 
     x:Key="WrappingImageListBox"> 
    <!-- Set the ItemTemplate of the ListBox to a DataTemplate 
     which explains how to display an object of type BitmapImage. --> 
    <Setter Property="ItemTemplate"> 
     <Setter.Value> 
      <DataTemplate> 
       <tcb:ThumbnailCheckBox ImagePath="{Binding ImagePath}" 
             IsChecked="{Binding Selected}" 
             Height="{TemplateBinding utilities:MyAttachedProperties.ImageSize}" 
             CornerRadius="8" 
             Margin="10"> 
       </tcb:ThumbnailCheckBox> 
      </DataTemplate> 
     </Setter.Value> 
    </Setter> 

    <!-- Swap out the default items panel with a WrapPanel so that 
     the images will be arranged with a different layout. --> 
    <Setter Property="ItemsPanel"> 
     <Setter.Value> 
      <ItemsPanelTemplate> 
       <WrapPanel /> 
      </ItemsPanelTemplate> 
     </Setter.Value> 
    </Setter> 

    <!-- Set this attached property to 'Disabled' so that the 
     ScrollViewer in the ListBox will never show a horizontal 
     scrollbar, and the WrapPanel it contains will be constrained 
     to the width of the ScrollViewer's viewable surface. --> 
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" 
      Value="Disabled" /> 
</Style> 

代碼2 - 列表框樣式

我這樣稱呼它從我的主視圖...

<ListBox ItemsSource="{Binding DirectoryPictures}" 
     Grid.Row="1" 
     Style="{DynamicResource WrappingImageListBox}" 
     Background="Transparent" 
     util:MyAttachedProperties.ImageSize="500"/> 

代碼3 - 主呼叫

此功能完全符合我的意願,但ImageSize屬性除外。 ImagePathSelected都是綁定到ListBox的單個列表項的屬性。你可以看到,我創建了一個附加屬性來嘗試傳遞值(500),但它似乎沒有工作。我應該注意到,我認爲我創建的樣式是正確的,因爲這些元素使用默認值。

public static class MyAttachedProperties 
{ 
    public static double GetImageSize(DependencyObject obj) 
    { 
     return (double)obj.GetValue(ImageSizeProperty); 
    } 

    public static void SetImageSize(DependencyObject obj, double value) 
    { 
     obj.SetValue(ImageSizeProperty, value); 
    } 

    public static readonly DependencyProperty ImageSizeProperty = 
     DependencyProperty.RegisterAttached(
      "ImageSize", 
      typeof(double), 
      typeof(MyAttachedProperties), 
      new FrameworkPropertyMetadata(50D)); 
} 

代碼4 - 附加屬性

在最後一行指定的50D正在申請上市的控制。如果我改變它,並重新編譯,最終結果會改變。但是我的ListBox主呼叫(清單3)中指定的500的發送值不會發送。當然,我最終希望將500更改爲我的視圖模型上的綁定屬性,但我不會那樣做,直到我得到它的顯式值。

有人可以幫我弄清楚如何從我的主ListBox調用(清單3)發送一個值,並將其應用到由模板填充的單個項目?其他屬性我有工作,但它們是列表中每個項目的屬性,我綁定到ListBox,而ImageSize不是。


編輯爲了解決第一個反應

這似乎是工作,但它是一種奇特。我的列表框現在被稱爲是這樣的...

<ListBox ItemsSource="{Binding DirectoryPictures}" 
     Grid.Row="1" 
     Style="{DynamicResource WrappingImageListBox}" 
     Background="Transparent" /> 

而且我已經改變了我的風格,給你建議的代碼...

<tcb:ThumbnailCheckBox ImagePath="{Binding ImagePath}" 
         IsChecked="{Binding Selected}" 
         Height="{Binding Path=DataContext.ThumbnailSize, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" 
         CornerRadius="8" 
         Margin="10"> 

我唯一擔心的是,現在的風格訪問該控件的ViewModel直接而不是接收綁定值。

假設我想再次使用ListBox,但在另一個UserControlViewModel沒有ThumbnailSize財產,而是由另一名使用一個?

你看到我要去的地方......目前的解決方案不是非常具有可擴展性,並且僅限於當前類,因爲它們的名字完全相同。

事實上,在一個完美的世界中,我想要爲ImagePathSelected屬性指定變量名稱,但這是一個不同的討論。

回答

1

可以使用FindAncestor。這個想法是,孩子遍歷邏輯樹,並試圖找到父類具體的類型(在這種情況下,ListBox),然後訪問附加的屬性。有關更多綁定表達式,請參見http://wpftutorial.net/BindingExpressions.html

在你ItemTemplate,你這是怎麼能訪問ThumbnailSize屬性:

{Binding Path=(util:MyAttachedProperties.ImageSize), 
     RelativeSource={RelativeSource 
          Mode=FindAncestor, 
          AncestorType={x:Type ListBox}}} 

從本質上講,這裏提出的問題是有點相反的,但結果是一樣的。 「在ListBox訪問ListBox(附後)屬性的項目

+0

怎麼可能作出的編輯到原來的職位詢問該解決方案由於 – imdandman 2015-01-09 21:31:19

+0

@imdandman一些問題;!對了,你的意思是有道理的,您可以綁定。你應該創建一個新的'UserControl'幷包裝'ListBox',並且顯示'ThumbnailSize'屬性。附加的屬性看起來很可疑。 – 2015-01-09 21:43:10

+0

這樣做了!謝謝!我想要複製它的角落半徑和邊距屬性。快速問題 - 是否有一種「更乾淨」的方式來做到這一點,而不是使用附加的屬性?爲所有這些屬性製作附加屬性是一種混亂,但它的工作原理並且比我在那裏看到的任何其他中途解決方案都更直接。再次感謝!這真棒。 – imdandman 2015-01-09 21:56:46