views:

29

answers:

3

I have ComboBox with CheckBoxes for items. When user checks or uncheckes boxes I want the selected values to be displayed in the ContentPresenter separated by comma. At the the moment I have overridden ContentPresenter:

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

ContentPresenter is a part of ComboBox style by default. Any hints on how to implement this feature?

ComboBox ItemTemplate is implemented like this:

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

I did not understand what you meant by "the ContentPresenter".

If you want a combox box, with the list of selected items as its text, I can explain how my son (who's not in SO) did it:

He put a grid with a ComboBox followed by a TextBlock. The ItemTemplate of the ComboBox includes a check box with a handler for the Checked and UnChecked events. In these events, he recomputed the Text property of the TextBlock, based on the selected state of the check boxes. Here is the 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>

I think one can do it without the TextBlock. Hopefully, this can put you in the right direction.

Timores
ContentPresenter is a part of ComboBox style by default
Dmitry
+1  A: 

This solution isn't ideal (for example, you can create custom control template for control inherited from combobox), but it works.

  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 of the combobox:

    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;
}
vorrtex
Thank you very much! Very usefull. I already had ItemTemplate, also I had a dependency property, but didn't know how to handle text information displayed in the contentpresenter of combobox. Strangely enough, silverlight combobox doesn't have means to override this via property.
Dmitry
A: 

The similar interesting post (WPF): http://stackoverflow.com/questions/2343446/default-text-for-templated-combo-box

Dmitry