2010-10-12 5 views
3

J'ai ComboBox avec CheckBoxes pour les articles. Lorsque l'utilisateur cocher ou décocher des cases, je souhaite que les valeurs sélectionnées soient affichées dans le ContentPresenter en les séparant par des virgules. Au moment je ContentPresenter substituée:Valeur d'affichage Combobox dans Silverlight

<ContentPresenter x:Name="ContentPresenter" 
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
    Margin="{TemplateBinding Padding}" 
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
    ContentTemplate="{StaticResource SelectedOperationsText}"/> 

ContentPresenter est une partie du style ComboBox par défaut. Des conseils sur la façon d'implémenter cette fonctionnalité?

ComboBox ItemTemplate est mis en œuvre comme ceci:

<DataTemplate x:Key="ComboItemTemplate"> 
    <Grid HorizontalAlignment="Left"> 
     <CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Text}"/> 
    </Grid> 
</DataTemplate> 

Répondre

3

Cette solution n'est pas idéale (par exemple, vous pouvez créer un modèle de contrôle personnalisé pour un contrôle hérité de la liste déroulante), mais cela fonctionne.

  1. Xaml

    <my:MyComboBox Width="180" ItemsSource="{Binding TestItems}" Text="{Binding SelectedItemsText}"> 
        <my:MyComboBox.ItemTemplate> 
         <DataTemplate> 
          <Grid HorizontalAlignment="Left"> 
           <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Text}"/> 
          </Grid> 
         </DataTemplate> 
        </my:MyComboBox.ItemTemplate> 
    </my:MyComboBox> 
    
  2. Hack de la liste déroulante:

    public class MyComboBox : ComboBox 
    { 
    private ContentPresenter selectedContent; 
    
    
    public MyComboBox() 
    { 
        this.DefaultStyleKey = typeof(ComboBox); 
    } 
    
    
    public override void OnApplyTemplate() 
    { 
        this.selectedContent = this.GetTemplateChild("ContentPresenter") as ContentPresenter; 
        this.RefreshContent(); 
        base.OnApplyTemplate(); 
        this.SelectionChanged += (s, e) => 
         { 
          //Cancel selection 
          this.SelectedItem = null; 
          this.RefreshContent(); 
         }; 
    } 
    
    
    public string Text 
    { 
        get { return (string)GetValue(TextProperty); } 
        set { SetValue(TextProperty, value); } 
    } 
    
    
    public static readonly DependencyProperty TextProperty = 
        DependencyProperty.Register("Text", typeof(string), typeof(MyComboBox), 
        new PropertyMetadata(null, new PropertyChangedCallback((s,e)=>((MyComboBox)s).RefreshContent()))); 
    
    
    private void RefreshContent() 
    { 
        if (this.selectedContent != null) 
        { 
         var tb = (TextBlock)this.selectedContent.Content; 
         tb.Text = this.Text; 
        } 
    } 
    } 
    
  3. MainViewModel

    public class MainViewModel : INotifyPropertyChanged 
    { 
    public MainViewModel() 
    { 
        this.InitializeTestItems(); 
    } 
    
    
    public void InitializeTestItems() 
    { 
        this.TestItems = new List<TestItemModel>{ 
           new TestItemModel{IsChecked=true, Text="first"}, 
           new TestItemModel{IsChecked=false, Text="second"}, 
           new TestItemModel{IsChecked=false, Text="third"}}; 
        this.RefreshSelectedItemsText(); 
        foreach (var item in this.TestItems) 
         item.CheckChanged += (s, e) => this.RefreshSelectedItemsText(); 
    } 
    
    
    private void RefreshSelectedItemsText() 
    { 
        SelectedItemsText = string.Join(", ", this.TestItems.Where(ti => ti.IsChecked).Select(ti => ti.Text)); 
    } 
    
    
    public List<TestItemModel> TestItems { get; set; } 
    
    
    private string selectedItemsText; 
    
    
    public string SelectedItemsText 
    { 
        get { return selectedItemsText; } 
        set 
        { 
         selectedItemsText = value; 
         OnPropertyChanged("SelectedItemsText"); 
        } 
    } 
    } 
    

4.ItemViewModel

public class TestItemModel 
{ 
    private bool isChecked; 

    public bool IsChecked 
    { 
     get { return isChecked; } 
     set 
     { 
      isChecked = value; 
      if (CheckChanged != null) 
       CheckChanged(this, null); 
     } 
    } 

    public string Text { get; set; } 

    public event EventHandler<EventArgs> CheckChanged; 
} 
+0

Merci beaucoup! Très utile. J'avais déjà ItemTemplate, j'avais aussi une propriété de dépendance, mais je ne savais pas comment gérer les informations textuelles affichées dans le contentpresenter de combobox. Assez étrangement, Silverlight combobox n'a pas les moyens de passer outre cette propriété. – Dmitry

0

Je ne comprenais pas ce que vous vouliez dire par "la ContentPresenter".

Si vous voulez une boîte Combox, la liste des éléments sélectionnés comme son texte, je peux expliquer comment mon fils (qui est pas SO) l'a fait:

Il a mis une grille avec un ComboBox suivi d'un TextBlock. Le ItemTemplate du ComboBox inclut une case à cocher avec un gestionnaire pour les événements Checked et UnChecked. Dans ces événements, il a recalculé la propriété Text du TextBlock, en fonction de l'état sélectionné des cases à cocher. Voici le XAML:

<Grid Name="LayoutRoot"> 
    <ComboBox ItemsSource="{Binding Path=SitesList}" Name="CBsites" DropDownOpened="ComboBox_DropDownOpened" DropDownClosed="ComboBox_DropDownClosed"> 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <CheckBox Content="{Binding Path=Location}" Checked="SiteCheckBox_Checked" Unchecked="SiteCheckBox_Unchecked" /> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 
    <TextBlock Name="TXTselected" IsHitTestVisible="False" VerticalAlignment="Center" Margin="6,0,0,0" /> 
</Grid> 

Je pense qu'on peut le faire sans TextBlock. J'espère que cela peut vous mettre dans la bonne direction.

+0

ContentPresenter est une partie de style ComboBox par défaut – Dmitry

0

J'ai créé un projet CodePlex ici: codeplex inspiré par ce blog et un certain nombre d'autres, s'il vous plaît vérifier et améliorer etc. Espérons que cela ou quelque chose comme il trouvera son chemin dans la boîte à outils ...

Je préfère ne pas avoir besoin d'un booléen de sélection dans les données liées donc j'ai apporté un SelectedItems bindable

Questions connexes