Question

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();
    }
}
Was it helpful?

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();

OTHER TIPS

I think you call SensorDevice's methord to get ambient or range value, so you can define your viewmodel class SensorDevice inherited from INotifyPropertyChanged interface, and define two property like Ambient or Range, and call OnPropertyChanged("Ambient"). After that, you need initialize your viewmodel in xaml , and pass it to tabcontrol's DataContext. Your usercontrol just binding to Ambient or Range property.

Code like this:

viewModel

public class SensorDevice : INotifyPropertyChanged
{
    private string _ambient = string.Empty;

    public string Ambient
    {
        get {return _ambient;}
        set 
        {
            _ambient = value;
            OnPropertyChanged("Ambient");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Xaml like:

<Window.Resources>
    <your_namespace_name:SensorDevice x:Key="DeviceVM" />
</Window.Resources>

<TabControl DataContext="{Binding Source={StaticResource DeviceVM}}">
    <TabItem Name="tabItemRanging"
             Header="{Binding Source={StaticResource strTabHeaderRanging}}">
        <TextBlock Text="{Binding Path=Ambient}" />
    </TabItem>
</TabControl>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top