从主窗口中的WPF用户控件访问对象 [英] Access objects in UserControl from MainWindow in WPF

查看:242
本文介绍了从主窗口中的WPF用户控件访问对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个简单的XAML,我怎么可以改变的的TextBlock 文本属性的UserControl1 主窗口

 <窗口x:类=RefactorXAML.MainWindow
的xmlns =http://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:X =HTTP:/ /schemas.microsoft.com/winfx/2006/xaml
的xmlns:refactorXaml =CLR的命名空间:RefactorXAML
标题=主窗口HEIGHT =350WIDTH =525>
<网格和GT;
< Grid.RowDefinitions>
< RowDefinition HEIGHT =100>< / RowDefinition>
< RowDefinition HEIGHT =100>< / RowDefinition>
< /Grid.RowDefinitions>
<网格和GT;
< refactorXaml:&的UserControl1 GT;< / refactorXaml:&的UserControl1 GT;
< /网格和GT;
将;网格Grid.Row =1>
<按钮和GT;改变文字< /按钮>
< /网格和GT;
< /网格和GT;
< /窗GT;

<用户控件X:类=RefactorXAML.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
MC:可忽略=D
D:DesignHeight =300D:DesignWidth =300>

< TextBlock的X:名称=MyTextblock>计算器< / TextBlock的>
< /用户控件>


解决方案

在WPF控件通常意味着是某种黑盒子。你不应该(而且通常不)关心里面是什么回事。相反,如果你想允许通信,定义控制可以与之通信的一个公共接口的用户。



在WPF中,这个公共接口通常使用的依赖属性。您可以使用正常的(CLR)属性的东西为好,但通常你想允许之类的数据绑定,然后你需要依赖属性。 Definining依赖属性是有点高于正常definining性能更加复杂,因为他们需要一些东西可以另外进行。在Visual Studio中,有 propdp 片段,虽然,这可以帮助你在几个简单的步骤,将所有的样板代码。



所以,对于用户的控制,我们有一个字符串属性,这是我们希望暴露给外界。因此,在代码隐藏该用户的控制,我们定义属性作为一个依赖项属性:

 公共部分类ExampleUserControl:用户控件
{
公共静态只读的DependencyProperty SomeTextProperty =
DependencyProperty.Register(SomeText则会上的typeof(串)的typeof(ExampleUserControl),新PropertyMetadata(默认值));

公共字符串SomeText
{
{返回(串)的GetValue(SomeTextProperty); }
集合{的SetValue(SomeTextProperty,值); }
}

//这是炒冷饭
公共ExampleUserControl()
{
的InitializeComponent();
}
}

这就是我们需要做的申报财产,其提供给您的组件的用户。现在我们只需要添加功能。由于没有涉及一些额外的逻辑,但你只是想委派值一些其他组件的属性(的TextBlocks的文本属性),我们可以只使用数据绑定。这就是将在大多数情况下工作:

 <用户控件X:类=SomeNamespace.ExampleUserControl... 
的DataContext ={绑定的RelativeSource = {自我的RelativeSource}}>
<&StackPanel的GT;
< TextBlock的文本={结合SomeText}/>
< / StackPanel的>
< /用户控件>



为了让数据绑定的属性来访问,我们设置为数据上下文自(即组件本身),然后我们就可以将数据绑定到其自身的属性。



在使用分量的话,我们可以只设置它的 SomeText 属性:

 <我:ExampleUserControl SomeText =富/> 

和因为它是一个依赖属性,我们还可以使用数据绑定来从其他地方获得的价值(例如,一个视图模型在使用MVVM):

 <我:ExampleUserControl SomeText ={结合SomeTextProperty}/> 



如果你给你的控制一个名字,你也可以访问它和它的> SomeText在后台代码,如果你需要做的属性:

 <我:ExampleUserControl X:名称=显示myControlSomeText =富/> 
<按钮点击=ChangeText_ClickCONTENT =更改文本/>





 私人无效ChangeText_Click(对象发件人,RoutedEventArgs E)
{
myControl.SomeText =酒吧;
}

在最后,我们有完全从应用程序分离的可重用组件它是在使用,而且该应用程序不需要知道关于该组件的执行,并且该组件不需要知道哪里它会被使用。


I have this simple XAML, how can I change the Text property of the TextBlock in UserControl1 from the MainWindow?

<Window x:Class="RefactorXAML.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:refactorXaml="clr-namespace:RefactorXAML"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="100"></RowDefinition>
            <RowDefinition Height="100"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid>
            <refactorXaml:UserControl1></refactorXaml:UserControl1>
        </Grid>
        <Grid Grid.Row="1">
            <Button>Change Text</Button>
        </Grid>
    </Grid>
</Window>

<UserControl x:Class="RefactorXAML.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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

        <TextBlock x:Name="MyTextblock">StackOverflow</TextBlock>
</UserControl>

解决方案

Controls in WPF are usually meant to be some kind of "black boxes". You shouldn’t (and usually don’t) care about what’s going on inside. Instead, if you want to allow communication, you define a public interface users of that control can communicate with.

In WPF, this public interface is usually made using dependency properties. You can use normal (CLR) properties for many things as well, but usually you want to allow things like data binding, and then you need dependency properties. Definining dependency properties is a bit more complicated than definining normal properties, as they require some stuff to be done additionally. In Visual Studio, there is the propdp snippet though, which helps you adding all that boilerplate code in a few simple steps.

So, for your user control, we have a single string property, which we want to expose to the outside. So in the code-behind for that user control, we define that property as a dependency property:

public partial class ExampleUserControl : UserControl
{
    public static readonly DependencyProperty SomeTextProperty =
        DependencyProperty.Register("SomeText", typeof(string), typeof(ExampleUserControl), new PropertyMetadata("default value"));

    public string SomeText
    {
        get { return (string)GetValue(SomeTextProperty); }
        set { SetValue(SomeTextProperty, value); }
    }

    // this is the same old stuff
    public ExampleUserControl()
    {
        InitializeComponent();
    }
}

That’s all we need to do to declare the property and make it available to users of your component. Now we just need to add the functionality. As there isn’t some extra logic involved, but as you just want to delegate the value to some other component’s property (TextBlocks’s Text property), we can just use data binding. That’s what will work for most cases:

<UserControl x:Class="SomeNamespace.ExampleUserControl" …
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <StackPanel>
        <TextBlock Text="{Binding SomeText}" />
    </StackPanel>
</UserControl>

To make the property accessible for data binding, we set the data context to self (i.e. to the component itself) and then we can data bind to its own properties.

When using the component then, we can just set the SomeText property of it:

<my:ExampleUserControl SomeText="Foo" />

And as it’s a dependency property, we can also use data binding to get the value from somewhere else (e.g. a view model when using MVVM):

<my:ExampleUserControl SomeText="{Binding SomeTextProperty}" />

And if you give your control a name, you can also access it and its SomeText property in code-behind if you need to do that:

<my:ExampleUserControl x:Name="myControl" SomeText="Foo" />
<Button Click="ChangeText_Click" Content="Change text" />

private void ChangeText_Click (object sender, RoutedEventArgs e)
{
    myControl.SomeText = "Bar";
}

In the end, we have a reusable component that is completely separated from the application it is used in. And the application does not need to know about the implementation of that component, and the component does not need to know about where it’s going to be used.

这篇关于从主窗口中的WPF用户控件访问对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆