当将代码移动到UserControl时,无法使绑定工作。

huangapple go评论78阅读模式
英文:

Can't get binding to work when moving to UserControl

问题

我们有一小段XAML代码想要重用。在这个例子中,我将它简化为一个文本框。

<TextBlock Text="{Binding MyProperty.Value}"/>

我们想要重用这个组件,所以我将它放在了一个UserControl中(不确定这是否是正确的方式)。请注意,数据绑定仍然是相同的:"{Binding MyProperty.Value}"

<controls:MyControl ControlValue="{Binding MyProperty.Value}"/>

这个组件是可以工作的,如果我在绑定中放入一个常量(例如"25"),它会按预期进行更新。但它不会对模型中的更改作出响应。

为什么原始的XAML可以工作,但使用UserControl时却不行?我在这里漏掉了什么?

MyControl.xaml

<UserControl
    x:Class="Project.UI.Elements.Common.Controls.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Project.UI.Elements.Common.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="25"
    d:DesignWidth="100">

    <TextBlock Text="{Binding ControlProperty}"/>
</UserControl>

MyControl.xaml.cs

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236

namespace Project.UI.Elements.Common.Controls
{
    public sealed partial class MyControl : UserControl
    {
        public static readonly DependencyProperty ControlValueProperty =
            DependencyProperty.Register("ControlValue", typeof(double), typeof(MyControl), new PropertyMetadata(0.0));

        public MyControl()
        {
            this.InitializeComponent();
            DataContext = this;
        }

        public double ControlValue
        {
            get { return (double)GetValue(ControlValueProperty); }
            set { SetValue(ControlValueProperty, value); }
        }
    }
}
英文:

We had a bit of XAML that we wanted to reuse. In this example, I've reduced it to a textbox.

&lt;TextBlock Text=&quot;{Binding MyProperty.Value}&quot;/&gt;

We want to reuse the component, so I put it in a UserControl. (Not sure if this is the right way) Note that the data binding is still the same; &quot;{Binding MyProperty.Value}&quot;

&lt;controls:MyControl ControlValue=&quot;{Binding MyProperty.Value}&quot;/&gt;

The component works, in that if I put a constant (e.g. &quot;25&quot;) instead of the binding, it is updated as expected.
But it doesn't respond to changes in the model.

Why does it work in the original XAML, but not with the UserControl? What am I missing here?

MyControl.xaml

&lt;UserControl
    x:Class=&quot;Project.UI.Elements.Common.Controls.MyControl&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:local=&quot;using:Project.UI.Elements.Common.Controls&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot;
    d:DesignHeight=&quot;25&quot;
    d:DesignWidth=&quot;100&quot;&gt;

    &lt;TextBlock Text=&quot;{Binding ControlProperty}&quot;/&gt;
&lt;/UserControl&gt;

MyControl.xaml.cs

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236

namespace Project.UI.Elements.Common.Controls
{
    public sealed partial class MyControl : UserControl
    {
        public static readonly DependencyProperty ControlValueProperty =
            DependencyProperty.Register(&quot;ControlValue&quot;, typeof(double), typeof(MyControl), new PropertyMetadata(0.0));

        public MyControl()
        {
            this.InitializeComponent();
            DataContext = this;
        }

        public double ControlValue
        {
            get { return (double)GetValue(ControlValue); }
            set { SetValue(ControlValue, value); }
        }
    }
}

答案1

得分: 1

根据您提供的当前场景,建议在UserControl中使用**{x:bind}**。

MainPage.xaml

<TextBlock Text="{Binding MainPageControlValue, Mode=OneWay}"/>
<local:MyControl ControlValue="{Binding MainPageControlValue, Mode=OneWay}"/>

MainPage.xaml.cs

public static readonly DependencyProperty MainPageValueProperty =
    DependencyProperty.Register("MainPageControlValue", typeof(string), typeof(MainPage), new PropertyMetadata("default"));

public MainPage()
{
    this.InitializeComponent();
    this.DataContext = this;
}

public string MainPageControlValue
{
    get { return (string)GetValue(MainPageValueProperty); }
    set { SetValue(MainPageValueProperty, value); }
}

MyControl.xaml

 <Grid>
    <TextBlock Text="{x:Bind ControlValue, Mode=OneWay}"/>
 </Grid>

MyControl.xaml.cs

public sealed partial class MyControl : UserControl
{
    public static readonly DependencyProperty ControlValueProperty =
        DependencyProperty.Register("ControlValue", typeof(string), typeof(MyControl), new PropertyMetadata("default"));

    public MyControl()
    {
        this.InitializeComponent();
    }
    public MyViewModel VM { get; set; }
    public string ControlValue
    {
        get { return (string)GetValue(ControlValueProperty); }
        set { SetValue(ControlValueProperty, value); }
    }
}

当您尝试使用x:bind时,请不要在UserControl中使用DataContext = this,否则将会出现以下绑定错误。

MainPageControlValue UserControlTest.MyControl.ControlValue,
Name='myControl' String BindingExpression path error:
'MainPageControlValue' property not found on
'UserControlTest.MyControl'

对于x:bind,DataContext是当前页面,它将在当前的Code-Behind类中查找属性。但对于Binding,默认情况下,它假设您绑定到标记页的DataContext。

如果您需要使用Binding,建议您使用自定义控件。您可以参考此线程

顺便提一下,在调试时,Visual Studio中有XAML绑定失败窗口和APP的顶部提示。

当将代码移动到UserControl时,无法使绑定工作。

当将代码移动到UserControl时,无法使绑定工作。

英文:

According to the current scenario you provided, it is recommended to use {x:bind} in UserControl.

MainPage.xaml

&lt;TextBlock Text=&quot;{Binding MainPageControlValue, Mode=OneWay}&quot;/&gt;
&lt;local:MyControl ControlValue=&quot;{Binding MainPageControlValue, Mode=OneWay}&quot;/&gt;

MainPage.xaml.cs

public static readonly DependencyProperty MainPageValueProperty =
    DependencyProperty.Register(&quot;MainPageControlValue&quot;, typeof(string), typeof(MainPage), new PropertyMetadata(&quot;default&quot;));

public MainPage()
{
    this.InitializeComponent();
    this.DataContext = this;
}

public string MainPageControlValue
{
    get { return (string)GetValue(MainPageValueProperty); }
    set { SetValue(MainPageValueProperty, value); }
}

MyControl.xaml

 &lt;Grid&gt;
    &lt;TextBlock Text=&quot;{x:Bind ControlValue, Mode=OneWay}&quot;/&gt;
 &lt;/Grid&gt;

MyControl.xaml.cs

public sealed partial class MyControl : UserControl
{
    public static readonly DependencyProperty ControlValueProperty =
        DependencyProperty.Register(&quot;ControlValue&quot;, typeof(string), typeof(MyControl), new PropertyMetadata(&quot;default&quot;));

    public MyControl()
    {
        this.InitializeComponent();
    }
    public MyViewModel VM { get; set; }
    public string ControlValue
    {
        get { return (string)GetValue(ControlValueProperty); }
        set { SetValue(ControlValueProperty, value); }
    }
}

Please don't use DataContext = this in UserControl When you try to use x:bind, otherwise you will get the following binding error.

> MainPageControlValue UserControlTest.MyControl.ControlValue,
> Name='myControl' String BindingExpression path error:
> 'MainPageControlValue' property not found on
> 'UserControlTest.MyControl'

For x:bind, the DataContext is current page, it will find the property in the current Code-Bebind class. But for Binding, assumes, by default, that you're binding to the DataContext of your markup page.

If you need to use Binding, it is recommended that you use Custom Control. You can refer to this thread.

By the way, there are XAML Binding Failures Window in Visual Studio and Top tips on APP when debugging.

当将代码移动到UserControl时,无法使绑定工作。

当将代码移动到UserControl时,无法使绑定工作。

答案2

得分: 0

BatteryLevelControl类中,你将数据上下文设置为this。然而,由于该类是从UserControl派生的,它不支持INotifyPropertyChanged,因此不会接收任何更改。尝试将数据上下文设置为从INotifyPropertyChanged派生的类,该类包含你的依赖属性。

英文:

in the BatteryLevelControl class, you set the data context to this. However, since the class is derived from UserControl, it does not support the INotifyPropertyChanged and thus does not receive any changes. Try setting the data context to your class that was derived from INotifyPropertyChanged and that contains your dependency properties.

huangapple
  • 本文由 发表于 2023年8月9日 14:23:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76865080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定