views:

326

answers:

2

I am currently learning to create custom controls in WPF. I successfully created a simple custom control using a Label and a Text Box. I was able to allow setting the Label text by DependencyProperty.

Now I am creating a user control that has a ComboBox. I need to allow adding items to this ComboBox from outside the control.

To achieve this, I tried exposing a DependencyProperty of type ItemsCollection and it will allows access to the ComboBox's Items property (the DP in my control sample is named 'CbItems'). But I get errors because Items property of Combobox is ReadOnly.

Control XAML

<UserControl x:Class="MyWpfApp.Controls.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="Auto" Width="Auto">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions> 
        <Label Grid.Column="0" Content="{Binding FieldLabel}"></Label>       
        <ComboBox Name="cmb"  Grid.Column="1" Width="150"></ComboBox>
    </Grid>
</UserControl>

MainWindow XAML

<Window x:Class="MyWpfApp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ctl="clr-namespace:MyWpfApp.Controls"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <ctl:MyControl>
            <ctl:MyControl.CbItems>
                <ComboBoxItem>Hello</ComboBoxItem>
                <ComboBoxItem>World</ComboBoxItem>
                <ComboBoxItem>Hi</ComboBoxItem>
            </ctl:LobCombox.CbItems>
        </ctl:LobCombox>
    </Grid>
</Window>

I would like to know what the correct way is to achieve this functionality. I believe the answer to this might also help with other controls like GridView etc

Many Thanks

+1  A: 

This great article from Dr. WPF contains all the information you will need, and a thorough explanation of all the options you can utilize.

Charlie
Thank you for the link. I solved the problem using CollectionViewSource.
byte
+2  A: 

WPF usually achieves many things through binding; it's a paradigm shift that takes some getting used to. Here's a quick example of some working code:

Window1.xaml

<Window
x:Class="ComboBoxSpike.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
Height="300"
Width="300">
<StackPanel>
    <ComboBox
        ItemsSource="{Binding ComboBoxItems}" />
    <Button
        x:Name="AddToComboBox"
        Content="Add an item to combo box"
        Click="AddToComboBox_Click" />
</StackPanel>
</Window>

Window1.xaml.cs

 public partial class Window1 : Window
{
    private ViewModel _viewModel;
    public static int Counter;

    public Window1()
    {
        InitializeComponent();
        _viewModel = new ViewModel();
        this.DataContext = _viewModel;
    }

    private void AddToComboBox_Click(object sender, RoutedEventArgs e)
    {
        _viewModel.ComboBoxItems.Add("ComboBoxItem" + Counter);
    }
}

public class ViewModel
{
    public ViewModel()
    {
        this.ComboBoxItems = new ObservableCollection<string>();
    }

    public ObservableCollection<string> ComboBoxItems { get; set; }


  }

The idea is that your ComboBox items are bound to a collection of strings (or any object for that matter, you can change the apperance of them with datatemplates). You don't make changes to the ComboBox itself, but to the collection of items it's bound to.

DavidN
Thank you David for the MVVM point of view. I solved my problem using CollectionViewSource from the article mentioned below by Charlie and few other online information on CollectionViewSource usage. I upvoted your answer.
byte