0
votes

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

2

2 Answers

2
votes

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

2
votes

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.