2016-10-17 5 views
1

Ich habe ContentControl und meine DataTemplateSelector auch Null-Wert unterstützen.Binding null Inhalt in ContentControl

<ContentControl Content="{x:Bind CurrentItem, Mode=OneWay}"> 
    <ContentControl.DataTemplateSelector> 
     <my:DataTemplateSelector> 
      <my:DataTemplateSelector.NullTemplate> 
       <DataTemplate> 
        <Border Background="Red" /> 
       </DataTemplate> 
      </my:DataTemplateSelector.NullTemplate> 
      <my:DataTemplateSelector.CustomTemplate1> 
       <DataTemplate> 
        <Border Background="Green" /> 
       </DataTemplate> 
      </my:DataTemplateSelector.CustomTemplate1> 
      <my:DataTemplateSelector.CustomTemplate2> 
       <DataTemplate> 
        <Border Background="Blue" /> 
       </DataTemplate> 
      </my:DataTemplateSelector.CustomTemplate2> 
     </my:DataTemplateSelector> 
    </ContentControl.DataTemplateSelector>     
</ContentControl> 

Das Problem ist, dass, wenn CurrentItem auf null ändert, ist es nicht SelectTemplateCore Methode in Datatemplateselector nicht nennen. Eigentlich ist NullTemplate nur ausgewählt, wenn das Steuerelement das erste Mal geladen wird und CurrentItem null ist.

Ich kann Null-Wert durch Dummy-Objekt ersetzen, aber es ist viel schwieriger, mit diesem Problem umzugehen. I this Lösung gefunden zu haben, aber es ist nur für WPF (UWP nicht Style.Triggers haben)

+0

Was wäre, wenn statt "x: Bind" eine 'Binding' mit einem expliziten' TargetNullValue' (oder einem 'Converter') verwendet wird, der einen Dummy-Wert zurückgibt. – Clemens

+0

Haben Sie meine Antwort überprüft? Irgendein Problem? –

Antwort

0

Ich bin nicht sicher, was ist Ihr ContentControl.DataTemplateSelector, nehme ich es die ContentControl.ContentTemplateSelector in UWP ist.

Das Problem ist, dass, wenn CurrentItem auf Null ändert, es nicht SelectTemplateCore-Methode in DataTemplateSelector aufrufen. Eigentlich ist NullTemplate nur ausgewählt, wenn das Steuerelement das erste Mal geladen wird und CurrentItem null ist.

Ja, Sie haben Recht damit. Wenn Sie CurrentItem später auf Null setzen, wird TemplateSelector nicht erneut in DataTemplateSelector laufen. Sie müssen eine Nullable-Eigenschaft für CurrentItem erstellen. Zum Beispiel:

<Page.Resources> 
    <DataTemplate x:Key="NullTemplate"> 
     <Border Background="Red" Height="300" Width="300"> 
      <TextBlock Text="{Binding TemplateName}" /> 
     </Border> 
    </DataTemplate> 
    <DataTemplate x:Key="CustomTemplate1"> 
     <Border Background="Green" Height="300" Width="300"> 
      <TextBlock Text="{Binding TemplateName}" /> 
     </Border> 
    </DataTemplate> 
    <DataTemplate x:Key="CustomTemplate2"> 
     <Border Background="Blue" Height="300" Width="300"> 
      <TextBlock Text="{Binding TemplateName}" /> 
     </Border> 
    </DataTemplate> 
    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector" 
            NullTemplate="{StaticResource NullTemplate}" 
            CustomTemplate1="{StaticResource CustomTemplate1}" 
            CustomTemplate2="{StaticResource CustomTemplate2}" /> 
</Page.Resources> 

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <ComboBox x:Name="combo" SelectionChanged="combo_SelectionChanged"> 
     <ComboBoxItem Content="NullTemplate" /> 
     <ComboBoxItem Content="CustomTemplate1" /> 
     <ComboBoxItem Content="CustomTemplate2" /> 
     <ComboBoxItem Content="SetCurrentItemToNull" /> 
     <ComboBoxItem Content="SetCurrentItemPropertyToNull" /> 
    </ComboBox> 
    <ContentControl Content="{x:Bind CurrentItem, Mode=OneWay}" Margin="0,10" 
        ContentTemplateSelector="{StaticResource MyDataTemplateSelector}" /> 
</StackPanel> 

Code hinter:

private ContentControlDataModel _CurrentItem; 

public ContentControlDataModel CurrentItem 
{ 
    get { return _CurrentItem; } 
    set 
    { 
     if (value != _CurrentItem) 
     { 
      _CurrentItem = value; 
      OnPropertyChanged(); 
     } 
    } 
} 

public event PropertyChangedEventHandler PropertyChanged; 

private void OnPropertyChanged([CallerMemberName]string propertyName = "") 
{ 
    if (this.PropertyChanged != null) 
    { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

private void combo_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    var item = combo.SelectedItem as ComboBoxItem; 
    switch (item.Content.ToString()) 
    { 
     case "NullTemplate": 
      CurrentItem = new ContentControlDataModel { Template = null, TemplateName = "NullTemplate" }; 
      break; 

     case "CustomTemplate1": 
      CurrentItem = new ContentControlDataModel { Template = true, TemplateName = "CustomTemplate1" }; 
      break; 

     case "CustomTemplate2": 
      CurrentItem = new ContentControlDataModel { Template = false, TemplateName = "CustomTemplate2" }; 
      break; 

     case "SetCurrentItemToNull": 
      CurrentItem = null; 
      break; 

     case "SetCurrentItemPropertyToNull": 
      CurrentItem = new ContentControlDataModel { Template = null, TemplateName = null }; 
      break; 

    } 
} 

ContentControlDataModel ist wie folgt:

public class ContentControlDataModel 
{ 
    public bool? Template { get; set; } //nullable property 
    public string TemplateName { get; set; } 
} 

und die MyDataTemplateSelector:

public class MyDataTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate NullTemplate { get; set; } 
    public DataTemplate CustomTemplate1 { get; set; } 
    public DataTemplate CustomTemplate2 { get; set; } 

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     var model = item as ContentControlDataModel; 
     if (model == null || model.Template == null) 
      return this.NullTemplate; 
     else 
     { 
      return (bool)model.Template ? this.CustomTemplate1 : this.CustomTemplate2; 
     } 
    } 
} 

Bild Rendering:

enter image description here

können Sie die Unterschiede überprüfen, indem verschiedene Elemente von ComboBox auswählen.

Verwandte Themen