我创建了一个新的TextBlock类,它具有ItemsSource属性并将ItemsSource转换为“Run”对象:
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 :(得分:0)
在您的示例中,SelectedItem
是否有两个属性Title
和Items
?或者Items
是您的viewmodel中的属性?如果答案是后者,那么你可以在下面找到解决方案。
我不完全明白你的意思,但我会试一试。
如果您的意思是未设置自定义控件上的ItemsSource
,则必须将XAML
指向正确的方向。
如果这是您想要实现的目标,您可以在下面找到解决方案。
我所做的是用这行代码将编译器指向正确的源代码:
ItemsSource="{Binding DataContext.Items, RelativeSource={RelativeSource AncestorType=Window}}"
在这里,您说编译器可以在窗口的Binding property
(或您可以找到DataContext
的任何控件)中找到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>
希望这会有所帮助。
修改强>
当我从title property
中选择另一个时,ListBox
会发生变化。
如果Items
设置为新的ObservableCollection
,那么当OnPropertyChanged event
更改时,您是否会Items
调用SelectedItem
?
OnPropertyChanged("Items");
答案 1 :(得分: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());
}
}
}
我将Binded的字段更新为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>