2016-01-13 31 views
0

我需要根據一定的條件在ItemsControl中添加不同的控件(TextBox/CheckBox/ComboBox等)。 ItemsControl中的每個項目都是名稱 - 值對。名稱始終由TextBlock表示,但Value可以是任何UI控件。 我使用水平對齊的StackPanel來表示每個項目。 StackPanel中的第一個控件仍然是TextBlock,但第二個控件依賴於ViewModel在運行時設置的「ItemDataType」屬性。在ItemsControl中添加不同的控件

我遇到的問題是,我無法使用帶有ItemDataType屬性的樣式觸發器在StackPanel的第2個元素中分配不同的控件。

代碼段:

<UserControl.Resources> 

    <DataTemplate x:Key="TextBoxTemplate"> 
     <TextBox Text="{Binding Path=DataValue}"/> 
    </DataTemplate> 

    <DataTemplate x:Key="ComboBoxTemplate"> 
     <ComboBox ItemsSource="{Binding Path=SelectionList}" SelectedValue="{Binding Path=DataValue,Mode=TwoWay}"/> 
    </DataTemplate> 

    <DataTemplate x:Key="CheckBoxTemplate"> 
     <CheckBox IsChecked="{Binding Path=DataValue,Mode=TwoWay}" /> 
    </DataTemplate> 

    <DataTemplate x:Key="ButtonTemplate"> 
     <Button Content="{Binding Path=DataValue}"/> 
    </DataTemplate> 

    <DataTemplate x:Key="dynamicTemplate"> 
     <StackPanel Orientation="Horizontal" Tag="{Binding ItemDataType}"> 
      <TextBlock Text="{Binding Path=DataName,Mode=TwoWay}"/> 
      <ContentControl> 
       <ContentControl.Style> 
        <Style TargetType="{x:Type ContentControl}"> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding ItemDataType}" Value="TextBox"> 
           <Setter Property="Template" Value="{StaticResource TextBoxTemplate}"/> 
          </DataTrigger> 
         </Style.Triggers> 
        </Style> 
       </ContentControl.Style> 
      </ContentControl> 
     </StackPanel> 
    </DataTemplate> 

</UserControl.Resources> 

<Grid> 
    <!-- CONTROL LAYOUT --> 
    <ItemsControl ItemsSource="{Binding Path=DataList,Mode=TwoWay}" ItemTemplate="{StaticResource dynamicTemplate}"> 

     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel></StackPanel> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</Grid> 

錯誤我得到的是DataTemplate中無效的ContentControl.Template財產。我明白我所做的是錯誤的,但我需要幫助正確地做到這一點。

感謝,

RDV

回答

0

答案(或一個答案)是寫一個DataTemplateSelector返回基於一些任意參數正確的模板。類似以下內容(請原諒所有空值檢查樣板噪音;這是直接從生產代碼中複製出來的)。

/// <summary> 
/// Selects template based on the value of a named property of the data item. 
/// Property name is specified by ResourceKeyPropertyName. 
/// </summary> 
public class PropertyValueTemplateSelector : DataTemplateSelector 
{ 
    /// <summary> 
    /// Gets or sets a path to a value on the source object to serve as a resource key for 
    /// the DataTemplate used to display the source object. 
    /// </summary> 
    public string ResourceKeyPropertyName { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     var context = container as FrameworkElement; 
     DataTemplate template = null; 

     if (null == container) 
     { 
      throw new NullReferenceException("container"); 
     } 
     else if (null == context) 
     { 
      throw new Exception("container must be FramekworkElement"); 
     } 
     else if (String.IsNullOrEmpty(ResourceKeyPropertyName)) 
     { 
      throw new NullReferenceException("ResourceKeyPropertyName"); 
     } 
     else if (null == item) 
     { 
      return null; 
     } 

     var prop = item.GetType().GetProperty(ResourceKeyPropertyName); 

     if (null == prop) 
     { 
      throw new Exception("Undefined property " + ResourceKeyPropertyName); 
     } 

     var resourceKey = prop.GetValue(item, null); 

     if (null != resourceKey) 
     { 
      try 
      { 
       template = context.FindResource(resourceKey) as DataTemplate; 
      } 
      catch (Exception ex) 
      { 
       Ability.CAPS.WPF.Utilities.ErrorHandler.HandleException(ex, Ability.Logging.AbilityExceptionPolicy.GeneralExceptionPolicy); 
       template = null; 
      } 
     } 

     return template ?? base.SelectTemplate(item, container); 
    } 
} 

使用像這樣的XAML:

<ItemsControl 
    > 
    <ItemsControl.ItemTemplateSelector> 
     <!-- Tell it use the value of the "DataName" property as the 
      resource key for the template it uses. 
     --> 
     <local:PropertyValueTemplateSelector 
      ResourceKeyPropertyName="DataName" /> 
    </ItemsControl.ItemTemplateSelector> 
    <!-- etc. 
     etc. 
     etc. --> 
</ItemsControl> 

如果某一商品的DataName屬性是「富」,這將看在當地背景的DataTemplate其資源的關鍵是「富」,並使用該 - 相應地命名您的DataTemplates並去鎮上。沒有更簡單或更普遍的方式來做到這一點。順便說一下,在我們的代碼中,目前僅在一個地方使用它(上個月我只寫了它),它使用的是資源鍵而不是字符串的枚舉值。任何對象都可以。資源鍵不一定是字符串。

或者,您可能想要查找某個內容或將DataName值轉換爲不同的密鑰集。你的電話,如果那樣更適合你的需求。

另一個選擇是具有一組觸發器,設置上的內 ContentControl中取決於DataName值的模板一個項目模板。 Here's an answer that does something like that

相關問題