How to Expose a Control in XAML

wpf, wpf-controls, xaml

Solution

You cannot access the child `DataGrid` as `MyControl.dataGrid` -- `MyControl` has no property named "dataGrid".

You might try adding a dependency property of type `ObservableCollection<DataGridColumn>` to `MyControl`, and modify the dataGrid columns whenever that collection changes.

EDIT: Whipped together a quick example for you:

UserControl code:

public partial class UserControl1 : UserControl
{
    public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register("Columns", typeof(ObservableCollection<DataGridColumn>), typeof(UserControl1));
    public ObservableCollection<DataGridColumn> Columns
    {
        get { return (ObservableCollection<DataGridColumn>)GetValue(ColumnsProperty); }
        set { SetValue(ColumnsProperty, value); }
    }


    public UserControl1()
    {
        Columns = new ObservableCollection<DataGridColumn>();
        Columns.CollectionChanged += (s, a) =>
            {
                dataGrid.Columns.Clear();
                foreach (var column in this.Columns)
                    dataGrid.Columns.Add(column);
            };
        InitializeComponent();
    }
}

UserControl xaml:

<UserControl x:Class="WpfApplication1.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
<Grid>
    <DataGrid x:Name="dataGrid" AutoGenerateColumns="False"/>
</Grid>

so you can use it like:

<Grid>
    <l:UserControl1>
        <l:UserControl1.Columns>
            <DataGridTextColumn Header="Col1"/>
            <DataGridTextColumn Header="Col2"/>
        </l:UserControl1.Columns>
    </l:UserControl1>
</Grid>

Problem

I'm new in WPF and I'm creating a control. This control contains a DataGrid and some other WPF controls. I created my Control as below: ``` <UserControl x:Class="MyControls.MyControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="329" d:DesignWidth="535" > <Grid> <DataGrid Margin="6,25,6,35" Name="dataGrid" SelectionUnit="CellOrRowHeader" x:FieldModifier="public" HeadersVisibility="All"/> <OtherControl HorizontalAlignment="Left" x:Name="otherControl" Height="34" VerticalAlignment="Bottom" Width="523" x:FieldModifier="private"/> <Label Content="caption" Height="24" HorizontalAlignment="Left" Name="captionLabel" VerticalAlignment="Top" Foreground="#FF2626D1" x:FieldModifier="private"/> </Grid> </UserControl> ``` So, everything goes well so far, then I create a container UserControl which has in it my control created previously: ``` <UserControl x:Class="MyContainers.MyContainer" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" xmlns:my="clr-namespace:MyControls"> <Grid> <my:MyControl> </my:MyControl> </Grid> ``` What I can not do is the following: ``` <my:MyControl> <my:MyControl.dataGrid> </my:MyControl.dataGrid> </my:MyControl> ``` I previously set the datagrid's property of `FieldModifier` as `public` in order to get access to it in another xaml, but it raises an error from visual studio. I need to "expose" my dataGrid in order to be able to add columns and their styles. I would like to be able to do something like this: ``` <my:MyControl.dataGrid.Columns > <DataGridTextColumn /> <DataGridTextColumn /> ... <DataGridTextColumn /> </my:MyControl.dataGrid.Columns> ``` So, is not enough to set the datagrid's property of `FieldModifier` as `public`? Do I need to do something else? How can I achieve this? Is this even possible? I hope someone can help me. Thank you in advance.

Original source