wpfuser-controlsrelativesource

WPF Passing data object from Main application UI to user control


I have user controls defined to represent the contents of tab items so as to split up a large XAML file into smaller files. I would like to pass reference to a data object from the main UI class to the user controls.

I understand that DependancyProperties and RelativeSource's are ways to achieve this but am not sure how to implement this due to my lack of WPF expertise. Can someone help me.

Thanks

I have three xaml files, MainWindow, AlsTabUC (UserControl) and RangingTabUC (UserControl). I have a single object representing a device that performs both range and ambient light measurements and wojuld like to perform these activities in separate tabs.

The object m_mySensorDevice is a member of MainWindow, which is the parent and I would like to pass this object to the two children so that they can execute readAmbientLight and readRange methods.

Naturally, I have provided very basic sample code for illustration. In reality these tabs contain much more information, (along with other tabs) hence the reason for the user controls.

MainWindow - XAML

    <Window.Resources>
        <System:String x:Key="strTabHeaderRanging">Ranging</System:String>
        <System:String x:Key="strTabHeaderALS">ALS</System:String>
    </Window.Resources>
    <Grid>
        <TabControl Name="MainTab" TabStripPlacement="Top"
                    Margin="0,20,0,10"
                    SelectionChanged="mainTab_SelectionChanged" >
            <TabItem Name="tabItemRanging"
                     Header="{Binding Source={StaticResource strTabHeaderRanging}}">
            <Grid>
                <my:rangingTabUC HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
                                 x:Name="rangingTabUC1"/>
            </Grid>
            </TabItem>
            <TabItem Name="tabItemAls"
                  Header="{Binding Source={StaticResource strTabHeaderALS}}">
                <Grid>
                    <my:AlsTabUC HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
                                 x:Name="alsTabUC1" /> 
                </Grid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

MainWindow - Code

public partial class MainWindow : Window
{
    SensorDevice m_mySensorDevice;
    public MainWindow()
    {
        m_mySensorDevice = new SensorDevice();
        InitializeComponent();
    }
    private void mainTab_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    }
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {

    }
}

public class SensorDevice
{
}

AlsTabUC - XAML

<UserControl x:Class="TabUserControls.AlsTabUC">
    <Grid>
        <Button Height="25" Width="100" Name="readAmbientLight"
                HorizontalAlignment="Center"  VerticalAlignment="Center"
                Click="readAmbientLight_Click" Margin="2">
            Read Amb Light
        </Button>
    </Grid>
</UserControl>

AlsTabUC - Code

public partial class AlsTabUC : UserControl
{
    public AlsTabUC()
    {
        InitializeComponent();
    }

    private void readAmbientLight_Click(object sender, RoutedEventArgs e)
    {
        m_mySensorDevice.readAmbientLight();
    }
}

rangingTabUC- XAML

<UserControl x:Class="TabUserControls.rangingTabUC">
    <Grid>
        <Button Height="25" Width="100" Name="readRange"
                HorizontalAlignment="Center"  VerticalAlignment="Center"
                Click="readRange_Click" Margin="2">
            Read Range
        </Button>  
    </Grid>
</UserControl>

rangingTabUC- Code

public partial class rangingTabUC : UserControl
{
    public rangingTabUC()
    {
        InitializeComponent();
    }

    private void readRange_Click(object sender, RoutedEventArgs e)
    {
        m_mySensorDevice.readRange();
    }
}

Solution

  • Since the UserControl are defined in XAML and are initialized by the code InitializeComponent of your MainWindow your are not able to use a constructor to pass a reference of your SensorDevice to the UserControls.

    Add a property SensorDevice to your UserControls AlsTabUC and rangingTabUC to pass a reference of your SensorDevice to your UserControls after InitializeComponent is called in your MainWindow.

    public SensorDevice Sensor {
        get;
        set;
    }
    

    Change the constructor of your MainWindow to the following

    public MainWindow()
    {
        m_mySensorDevice = new SensorDevice();
        InitializeComponent();
    
        // Pass reference of SensorDevice to UserControls
        rangingTabUC1.Sensor = m_mySensorDevice; 
        alsTabUC1.Sensor = m_mySensorDevice;
    }
    

    In your UserControls you can use the property to call the methods on your SensorDevice

    SensorDevice.readAmbientLight();
    

    or

    SensorDevice.readRange();