2015-10-12 60 views
1

我有這個ListViewUniversal Apps:如何將ListViewItem(容器)的屬性綁定到實際項目(View Model)?

<ListView ItemsSource="{Binding Items}"> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="ListViewItem"> 
      <Setter Property="Background" Value="{Binding IsValid, Converter={StaticResource BooleanToBrushConverter}" /> 
     </Style> 
    </ListView.ItemContainerStyle> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Name}" /> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

我知道綁定不會對二傳手的通用應用程序工作,但,那我怎麼綁定與該項目本身進行的容器?如果你不能提供任何邏輯,但創建一個自定義容器,但是常量值是什麼?

+1

我一直只用{結合OBJECTPROPERTY}在DataTemplate中。作爲一種解決方法,您可以簡單地在DataTemplate內部的TextBlock邊框周圍使用相同的Background聲明。 當您運行應用程序時,您是否在輸出窗口中看到任何BindingExpression錯誤?它是否達到了一個斷點? –

+0

@MarkW綁定風格的Setters不能在Windows運行時/ UWP中工作。 [OP知道這一事實](http://stackoverflow.com/q/33052081/1136211)。 – Clemens

+0

@clemens OP意識到問題,沒有人提供解決方案。我創建了一個自定義容器,無法綁定到它。在WPF中這很常見,我認爲有一個解決方案。沒有FindAncestor,也沒有綁定Setter。我無法相信這種正常情況是不可能解決的。 – SuperJMN

回答

1

OK,你不能用正常的方式綁定到DataContext,但您可以使用其他(智能)方法做到這一點

請看看這個帖子。它提供了一個「助手」,允許用Setter綁定到DataContext。

http://dlaa.me/blog/post/10089023

1

你需要小心在UWP ListViewItem的背景,因爲有很多複雜的主題化的解決這個包括不同種類的壓制和阻力背景

我認爲,一個更簡單的方式實現這一目標是改變在ListViewItem內容比對,然後將網格添加到您的項目模板,從中可以添加你的背景

<ListView ItemsSource="{Binding Items}"> 
<ListView.ItemContainerStyle> 
    <Style TargetType="ListViewItem"> 
     <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 
     <Setter Property="VerticalContentAlignment" Value="Stretch"/> 
    </Style> 
</ListView.ItemContainerStyle> 
<ListView.ItemTemplate> 
    <DataTemplate> 
     <Grid Background="{Binding Path=IsValid, Converter={StaticResource BooleanToBrushConverter}}"> 
      <TextBlock Text="{Binding Name}" VerticalAlignment="Center" /> 
     </Grid> 
    </DataTemplate> 
</ListView.ItemTemplate> 

+0

謝謝,Dean,但是如果我有自己的ItemContainer和一個自定義屬性怎麼辦?從DataTemplate我沒有任何方式綁定到ItemContainer。 – SuperJMN

+0

它可以工作,但項目邊框和網格之間有一個邊距。有沒有辦法解決它? – kokokok

-1

這是很容易的,真的。

我猜你試圖使用可變大小的網格視圖?實際上,這是一個相當常見的要求。但是,由於各種範圍以及如何呈現,你所要求的是棘手的。

第一個想你需要做的就是用你自己的自定義ListView覆蓋ListView。我們稱之爲MyListView。就像這樣:

public class MyItem 
{ 
    public int RowSpan { get; set; } 
    public int ColSpan { get; set; } 
} 

public class MyListView : ListView 
{ 
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item) 
    { 
     var model = item as MyItem; 
     try 
     { 
      element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, model.ColSpan); 
      element.SetValue(VariableSizedWrapGrid.RowSpanProperty, model.RowSpan); 
     } 
     catch 
     { 
      element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, 1); 
      element.SetValue(VariableSizedWrapGrid.RowSpanProperty, 1); 
     } 
     finally 
     { 
      element.SetValue(VerticalContentAlignmentProperty, VerticalAlignment.Stretch); 
      element.SetValue(HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch); 
      base.PrepareContainerForItemOverride(element, item); 
     } 
    } 
} 

一切都發生在PrepareContainerForItemOverride的地方,您需要重寫子類中的唯一方法。請注意,我沒有設置它們的綁定。這是因爲這些屬性僅在渲染項目時才被觀察到。如果您想刷新ListView並根據新值重新渲染項目,則需要在根面板上調用InvalidateMeasure(),這很棘手。你可以這樣做:

// MyListView 

public void Update() 
{ 
    if (!(this.ItemsPanelRoot is VariableSizedWrapGrid)) 
     throw new ArgumentException("ItemsPanel is not VariableSizedWrapGrid"); 

    foreach (var container in this.ItemsPanelRoot.Children.Cast<GridViewItem>()) 
    { 
     var model = item as MyItem; 
     VariableSizedWrapGrid.SetRowSpan(container, data.RowSpan); 
     VariableSizedWrapGrid.SetColumnSpan(container, data.ColSpan); 
    } 

    this.ItemsPanelRoot.InvalidateMeasure(); 
} 

如果這是有道理的,你可以看到整個實現here

祝你好運!

+0

如果它是您正在使用的變量網格,您可能會喜歡此博客文章:http://blog.jerrynixon.com/2012/08/windows-8-beauty-tip-using.html –

+0

此方法的問題是它幾乎不可重複使用:( – SuperJMN

+1

好吧,不是所有的都是。 –

相關問題