WPF 将数据对象从主应用程序 UI 传递到用户控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17015050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:58:27  来源:igfitidea点击:

WPF Passing data object from Main application UI to user control

wpfuser-controlsrelativesource

提问by user1400716

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.

我定义了用户控件来表示选项卡项的内容,以便将大型 XAML 文件拆分为较小的文件。我想将对数据对象的引用从主 UI 类传递给用户控件。

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.

我知道 DependancyProperties 和 RelativeSource 是实现这一目标的方法,但由于我缺乏 WPF 专业知识,我不确定如何实现这一点。有人能帮我吗。

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.

我有三个 xaml 文件,MainWindow、AlsTabUC (UserControl) 和 RangingTabUC (UserControl)。我有一个对象代表一个设备,它执行范围和环境光测量,并且想在单独的选项卡中执行这些活动。

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.

对象 m_mySensorDevice 是 MainWindow 的成员,它是父级,我想将此对象传递给两个子级,以便他们可以执行 readAmbientLight 和 readRange 方法。

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

主窗口 - 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

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

AlsTabUC - 代码

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

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

rangingTabUC- XAML

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

rangingTabUC- Code

测距TabUC- 代码

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

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

采纳答案by Jehof

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.

由于 UserControl 在 XAML 中定义并由 MainWindow 的 InitializeComponent 代码初始化,因此您无法使用构造函数将 SensorDevice 的引用传递给 UserControl。

Add a property SensorDeviceto your UserControls AlsTabUCand rangingTabUCto pass a reference of your SensorDevice to your UserControls after InitializeComponentis called in your MainWindow.

SensorDevice在您的 UserControls 中添加一个属性,AlsTabUC并在 MainWindow 中调用rangingTabUC之后将您的 SensorDevice 的引用传递给您的 UserControls InitializeComponent

public SensorDevice Sensor {
    get;
    set;
}

Change the constructor of your MainWindowto the following

将您的构造函数更改MainWindow为以下内容

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

在您的 UserControls 中,您可以使用该属性来调用 SensorDevice 上的方法

SensorDevice.readAmbientLight();

or

或者

SensorDevice.readRange();

回答by muzizongheng

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.

我认为您调用 SensorDevice 的方法来获取环境或范围值,因此您可以定义从 INotifyPropertyChanged 接口继承的视图模型类 SensorDevice,并定义两个属性,如 Ambient 或 Range,并调用 OnPropertyChanged("Ambient")。之后,您需要在 xaml 中初始化您的视图模型,并将其传递给 tabcontrol 的 DataContext。您的用户控件仅绑定到 Ambient 或 Range 属性。

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:

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