2010-06-01 52 views
1

我有一个数据源('SampleAppearanceDefinitions'),它包含一个集合('Definitions')。集合中的每个项目都有几个属性,包括Color,这是我在这里感兴趣的。WPF - 动态访问XAML中集合的特定项目

我希望在XAML中将集合中特定项目的颜色显示为文本。我可以做到这一点就好用下面这段代码...

Text="{Binding Source={StaticResource SampleAppearanceDefinitions}, Path=Definitions[0].Color}" 

唯一的问题是,这需要我硬编码定义集合中的项目的索引(我在这个例子中使用0以上)。我想要做的事实上是从我当前的DataContext('AppearanceID')中的属性中获取该值。有人可能会想象正确的代码看起来像这样......

Text="{Binding Source={StaticResource SampleAppearanceDefinitions}, Path=Definitions[{Binding AppearanceID}].Color}" 

......但当然,这是错误的。

任何人都可以告诉我做正确的方法是什么?仅在XAML中可能吗?感觉应该是这样,但我无法解决或找到如何去做。

任何帮助将不胜感激!

谢谢!

AT

回答

0

即使它可能是可能的,你最好不要做这种方式,而是在您的视图模型或视图的后面的代码使用专用的财产,如果它只有一个纯粹的图形含义。

此属性,说“CurrentAppearance”,会暴露你可以从你的XAML绑定一个颜色属性:

Text="{Binding CurrentAppearance.Color}" 

这是更容易理解。

作为一般性建议:避免破坏你的Xaml管道代码:Xaml应该尽可能易读, 特别是如果你与一个没有编码技能并且不想关心你管理数据的方式。此外,如果稍后您决定更改数据管理方式,则不必更改Xaml。

1

MultiBinding是你的朋友在这里:

假设你有一个TextBlock:

<TextBlock> 
    <TextBlock.Text> 
     <MultiBinding Converter="{StaticResource AppearanceIDConverter}"> 
      <Binding Source="{StaticResource SampleAppearanceDefinitions}" /> 
      <Binding Path="AppearanceID" /> 
     </MultiBinding> 
    </TextBlock.Text> 
</TextBlock> 

,并定义一个MultiValueConverter返回你希望看到什么:

public class AppearanceIDConverter : IMultiValueConverter 
{ 
    #region IMultiValueConverter Members 

    public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     List<item> items = (List<item>)values[0]; //Assuming its items in a List 
     int id = (int)values[1]; //Assuming AppearanceID is an integer 
     return items.First(i => i.ID == id).Color; //Select your item based on the appearanceID.. I used LINQ, but a foreach will work just fine as well 
    } 

    public object[] ConvertBack(object value, System.Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new System.NotImplementedException(); 
    } 

    #endregion 
} 

当然,你将需要将转换器设置为资源字典中的资源,就像您制作SampleAppearanceDefinitions一样。如果可以通过代码访问SampleAppearanceDefinitions集合,也可以使用IValueConverter禁用多重绑定并使用常规绑定到AppearanceID;)。

希望这有助于如果您的列表是在视图模型,而不是一个静态资源

+0

它将如何与TwoWay绑定工作? – Pragmateek 2010-06-01 12:49:39

+0

如果您希望多个数据可用于您的价值,您可以使用MultiBinding而不是普通的Binding;对于双向绑定,您将不得不在ConvertBack方法中提供一些逻辑。 – Arcturus 2010-06-02 06:52:56

+0

准确地说,这个实现看起来并不明显:检索哪个对象是集合,哪个集合以及哪个索引的边界值是棘手的;如果它存在于多个集合中呢?转换器需要更多的上下文:我想这个上下文可以通过ConverterParameter传递,但是产生的Xaml可能很重。你能提供一个简单的实现吗?谢谢。 – Pragmateek 2010-06-02 09:03:47

0

MultiBinding可能实际工作。我惊讶地发现,传递给视图的对象实际上是一个指向模型上对象的指针,所以改变视图中的对象(例如,在文本框中键入新测试)将直接影响模型对象。

这对我有效。 ConvertBack方法从不使用。

public class PropertyIdToPropertyConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (values.Length == 2) 
     { 
      var properties = values[0] as ObservableCollection<PropertyModel>; 

      if (properties != null) 
      { 
       var id = (int)values[1]; 
       return properties.Where(model => model.Id == id).FirstOrDefault(); 
      } 
     } 

     return null; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
}