WPF Передача объекта данных из пользовательского интерфейса основного приложения в пользовательский элемент управления

У меня есть пользовательские элементы управления, определенные для представления содержимого элементов вкладки, чтобы разделить большой файл XAML на более мелкие файлы. Я хотел бы передать ссылку на объект данных из основного класса пользовательского интерфейса в пользовательские элементы управления.

Я понимаю, что DependancyProperties и RelativeSource - способы достижения этого, но я не уверен, как реализовать это из-за моего недостатка опыта WPF. Кто-нибудь может мне помочь.

Спасибо

У меня есть три xaml-файла: MainWindow, AlsTabUC (UserControl) и RangingTabUC (UserControl). У меня есть один объект, представляющий устройство, которое выполняет измерения дальности и внешней освещенности, и мне бы хотелось выполнять эти действия в отдельных вкладках.

Объект m_mySensorDevice является членом MainWindow, который является родителем, и я хотел бы передать этот объект двум дочерним элементам, чтобы они могли выполнять методы readAmbientLight и readRange.

Естественно, я предоставил очень простой пример кода для иллюстрации. На самом деле эти вкладки содержат гораздо больше информации (наряду с другими вкладками), следовательно, причина для пользовательских элементов управления.

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 - Код

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 - Код

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

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

ранжирование TABUC- 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>

RangeTabUC- Код

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

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

2 ответа

Решение

Поскольку UserControl определены в XAML и инициализируются кодом InitializeComponent вашего MainWindow, вы не можете использовать конструктор для передачи ссылки на SensorDevice в UserControls.

Добавить недвижимость SensorDevice в ваши UserControls AlsTabUC а также rangingTabUC передать ссылку на свой SensorDevice в UserControls после InitializeComponent вызывается в вашем MainWindow.

public SensorDevice Sensor {
    get;
    set;
}

Измените конструктор вашего MainWindow к следующему

public MainWindow()
{
    m_mySensorDevice = new SensorDevice();
    InitializeComponent();

    // Pass reference of SensorDevice to UserControls
    rangingTabUC1.Sensor = m_mySensorDevice; 
    alsTabUC1.Sensor = m_mySensorDevice;
}

В ваших UserControls вы можете использовать свойство для вызова методов вашего SensorDevice

SensorDevice.readAmbientLight();

или же

SensorDevice.readRange();

Я думаю, что вы вызываете метод SensorDevice для получения значения окружения или диапазона, поэтому вы можете определить свой класс модели представления SensorDevice, унаследованный от интерфейса INotifyPropertyChanged, и определить два свойства, таких как Ambient или Range, и вызвать OnPropertyChanged("Ambient"). После этого вам нужно инициализировать вашу модель представления в xaml и передать ее в DataContext tabcontrol. Ваш usercontrol просто привязывается к свойству Ambient или Range.

Код как это:

ViewModel

public class SensorDevice : INotifyPropertyChanged

{приватная строка _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, как:

<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>

Другие вопросы по тегам