2013-10-23 65 views
1

我創建了具有ItemsSource屬性和那個翻譯成的ItemsSource「運行」對象的新TextBlock類:改變的DataContext不更新列表域

public class MultiTypeDynamicTextBlock : TextBlock 
{ 
    public interface ISection 
    { 
     Inline GetDisplayElement(); 
    } 

    public class TextOption : ISection 
    { 
     private Run mText; 

     public TextOption(string aText) 
     { 
      mText = new Run(); 
      mText.Text = aText.Replace("\\n", "\n"); 
     } 

     public Inline GetDisplayElement() 
     { 
      return mText; 
     } 
    } 

    public class LineBreakOption : ISection 
    { 
     public Inline GetDisplayElement() 
     { 
      return new LineBreak(); 
     } 

     public ISection Clone() 
     { 
      return new LineBreakOption(); 
     } 
    } 

    public class ImageOption : ISection 
    { 
     private InlineUIContainer mContainer; 

     public ImageOption(string aDisplay) 
     { 
      Image lImage; 
      lImage = new Image(); 
      lImage.Source = new BitmapImage(new Uri(Environment.CurrentDirectory + aDisplay)); 
      lImage.Height = 15; 
      lImage.Width = 15; 
      mContainer = new InlineUIContainer(lImage); 
     } 

     public Inline GetDisplayElement() 
     { 
      return mContainer; 
     } 
    } 

    public static readonly DependencyProperty ItemsSourceProperty = 
     DependencyProperty.Register("ItemsSource", typeof(ObservableCollection<ISection>), typeof(MultiTypeDynamicTextBlock), 
     new UIPropertyMetadata(new ObservableCollection<ISection>(), 
     new PropertyChangedCallback(SetContent))); 

    public ObservableCollection<ISection> ItemsSource 
    { 
     get 
     { 
      return GetValue(ItemsSourceProperty) as ObservableCollection<ISection>; 
     } 
     set 
     { 
      if (ItemsSource != null) 
       ItemsSource.CollectionChanged -= CollectionChanged; 
      SetValue(ItemsSourceProperty, value); 
      SetContent(); 
      ItemsSource.CollectionChanged += CollectionChanged; 
     } 
    } 

    private void CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     SetContent(); 
    } 

    private static void SetContent(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     DependencyObject lParent = d; 
     MultiTypeDynamicTextBlock lPanel = lParent as MultiTypeDynamicTextBlock; 
     if (lPanel != null) 
     { 
      lPanel.ItemsSource = e.NewValue as ObservableCollection<ISection>; 
     } 
    } 

    private void SetContent() 
    { 
     if (ItemsSource != null) 
     { 
      Inlines.Clear(); 
      foreach (ISection lCurr in ItemsSource) 
      { 
       Inlines.Add(lCurr.GetDisplayElement()); 
      } 
     } 
    } 

如果我直接綁定的ItemsSource到DataContext,它的工作原理。 但是,如果我將它綁定到在運行時發生更改的對象(如ListBox上的SelectedItem),它將不會在選擇新項目時更新文本。

<StackPanel> 
    <ListBox x:Name="TheList" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Title}"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <StackPanel DataContext="{Binding ElementName=TheList, Path=SelectedItem}"> 
     <TextBlock Text="{Binding Title}" FontSize="20"/> 
     <local:MultiTypeDynamicTextBlock ItemsSource="{Binding Items}"/> 
    </StackPanel> 
</StackPanel> 

任何原因?

+0

你是什麼意思是「如果我直接綁定的ItemsSource到DataContext,它的作品。」?你提到的xaml的例子是工作還是非工作的例子? – Nitin

+0

Add this ItemsSource =「{Binding}」 – Aravind

+0

「Items」集合中對象的類型是什麼? – Loetn

回答

0

在你的例子中,SelectedItem有兩個屬性TitleItems?或者是Items您的viewmodel屬性?如果答案是後者,則可以在下面找到解決方案。

我不完全明白你的意思,但我會試試看。 如果您的意思是您的自定義控件上的ItemsSource未設置,則必須將XAML指向正確的方向。 下面你可以找到一個解決方案,如果這是你想要實現的。 我所做的是指向編譯器的右側源與這行代碼:

ItemsSource="{Binding DataContext.Items, RelativeSource={RelativeSource AncestorType=Window}}" 

在這裏你說的編譯器可以在窗口DataContextBinding property(或在那裏你可以找到任何控制property)。

<StackPanel> 
     <ListBox x:Name="TheList" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Title}"/> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
     <StackPanel DataContext="{Binding ElementName=TheList, Path=SelectedItem}"> 
      <TextBlock Text="{Binding Title}" FontSize="20"/> 
      <local:MultiTypeDynamicTextBlock ItemsSource="{Binding DataContext.Items, RelativeSource={RelativeSource AncestorType=Window}}"/> 
     </StackPanel> 
    </StackPanel> 

希望這有助於。


編輯

當我選擇從ListBox一個又一個的title property會發生變化。 如果Items設置爲新的ObservableCollection,那麼SelectedItem更改時是否撥打OnPropertyChanged event代替Items

OnPropertyChanged("Items"); 
+0

你是對的,問題不明確 答案是第一個,所選項目有2個屬性,標題和項目,當選擇一個新記錄時,標題被更新但項目不是 – user2342987

+0

@ user2342987好的。請參閱我的編輯:) – Loetn

+0

首先,項目沒有更改,我們正在查看不同的項目(屬於該類別的另一個實例)。其次,我添加了這個代碼,但它仍然無效。 – user2342987

0

謝謝你的幫忙。 我設法通過更新MultiTypeDynamicTextBlock解決這個問題如下:

public class MultiTypeDynamicTextBlock : TextBlock 
{ 
    public interface ISection 
    { 
     Inline GetDisplayElement(); 

     ISection Clone(); 
    } 

    public class TextOption : ISection 
    { 
     private Run mText; 

     public TextOption(string aText) 
     { 
      mText = new Run(); 
      mText.Text = aText.Replace("\\n", "\n"); 
     } 

     public Inline GetDisplayElement() 
     { 
      return mText; 
     } 

     public ISection Clone() 
     { 
      return new TextOption(mText.Text); 
     } 
    } 

    public class LineBreakOption : ISection 
    { 
     public Inline GetDisplayElement() 
     { 
      return new LineBreak(); 
     } 

     public ISection Clone() 
     { 
      return new LineBreakOption(); 
     } 
    } 

    public class SectionList 
    { 
     private ObservableCollection<ISection> mList; 

     public Action CollectionChanged; 

     public ObservableCollection<ISection> Items 
     { 
      get 
      { 
       ObservableCollection<ISection> lRet = new ObservableCollection<ISection>(); 
       foreach (ISection lCurr in mList) 
       { 
        lRet.Add(lCurr.Clone()); 
       } 
       return lRet; 
      } 
     } 

     public int Count { get { return mList.Count; } } 

     public SectionList() 
     { 
      mList = new ObservableCollection<ISection>(); 
     } 

     public void Add(ISection aValue) 
     { 
      mList.Add(aValue); 
     } 

     public SectionList Clone() 
     { 
      SectionList lRet = new SectionList(); 
      lRet.mList = Items; 
      return lRet; 
     } 
    } 

    public MultiTypeDynamicTextBlock() 
    { 

    } 

    public static readonly DependencyProperty ItemsCollectionProperty = 
     DependencyProperty.Register("ItemsCollection", typeof(SectionList), typeof(MultiTypeDynamicTextBlock), 
      new UIPropertyMetadata((PropertyChangedCallback)((sender, args) => 
      { 
       MultiTypeDynamicTextBlock textBlock = sender as MultiTypeDynamicTextBlock; 
       SectionList inlines = args.NewValue as SectionList; 

       if (textBlock != null) 
       { 
        if ((inlines != null) && (inlines.Count > 0)) 
        { 
         textBlock.ItemsCollection.CollectionChanged += textBlock.ResetInlines; 
         textBlock.Inlines.Clear(); 
         foreach (ISection lCurr in textBlock.ItemsCollection.Items) 
         { 
          textBlock.Inlines.Add(lCurr.GetDisplayElement()); 
         } 
        } 
        else 
        { 
         inlines = new SectionList(); 
         inlines.Add(new TextOption("No value set")); 
         textBlock.ItemsCollection = inlines; 
        } 
       } 
      }))); 

    public SectionList ItemsCollection 
    { 
     get 
     { 
      return (SectionList)GetValue(ItemsCollectionProperty); 
     } 
     set 
     { 
      SectionList lTemp; 
      if (value == null) 
      { 
       lTemp = new SectionList(); 
       lTemp.Add(new TextOption("No value set for property")); 
      } 
      else 
      { 
       lTemp = value; 
      } 
      SetValue(ItemsCollectionProperty, lTemp); 
     } 
    } 

    private void ResetInlines() 
    { 
     Inlines.Clear(); 
     foreach (ISection lCurr in ItemsCollection.Items) 
     { 
      Inlines.Add(lCurr.GetDisplayElement()); 
     } 
    } 
} 

我更新被綁定爲類型MultiTypeDynamicTextBlock.SectionList

只要我使用的是複製的字段(克隆)它正在工作,出於某種原因,當我不克隆它時,會從列表中的顯示中刪除值,如果有人知道我爲什麼喜歡學習,但我設法解決它。 窗口的XAML是:

<StackPanel> 
    <ListBox x:Name="TheList" ItemsSource="{Binding GeneralItems}" SelectedItem="{Binding SelectedItem}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel> 
        <TextBlock Text="{Binding Title}" FontSize="20"/> 
        <local:MultiTypeDynamicTextBlock ItemsCollection="{Binding Items}" Margin="20,0,0,0"/> 
       </StackPanel> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <StackPanel DataContext="{Binding GeneralItems, Path=SelectedItem}"> 
     <TextBlock Text="{Binding Title}" FontSize="20"/> 
     <local:MultiTypeDynamicTextBlock DataContext="{Binding Items}" ItemsCollection="{Binding}" Margin="20,0,0,0"/> 
    </StackPanel> 
</StackPanel> 
相關問題