简体   繁体   English

数据绑定到我的用户控件的依赖项属性不起作用

[英]Databinding to dependency properties of my user control doesn't work

I am making a user control to represent chosen numbers (like in a lottery). 我正在制作一个用户控件来表示选定的数字(例如在彩票中)。 The problem is that when binding to it inside a data template binding does not work. 问题是,在数据模板中绑定到它时,绑定不起作用。 It works correclty when hardcoding the values. 对值进行硬编码时,它可以正确处理。

The errors are of this type and they appear for every dependency property I bind to 错误属于这种类型,对于我绑定到的每个依赖项属性都将出现

Error: BindingExpression path error: 'BackCheckedColor' property not found on 'NumberControlTest.Controls.NumberControl'. BindingExpression: Path='BackCheckedColor' DataItem='NumberControlTest.Controls.NumberControl'; target element is 'NumberControlTest.Controls.NumberControl' (Name='null'); target property is 'CheckedBackgroundColor' (type 'String')

What I find strange is that in this section of the error BindingExpression: Path='BackCheckedColor' DataItem='NumberControlTest.Controls.NumberControl' It suggests that it is trying to find the BackCheckedColor in the usercontrol itself. 我发现奇怪的是,在错误BindingExpression: Path='BackCheckedColor' DataItem='NumberControlTest.Controls.NumberControl'这一部分中BindingExpression: Path='BackCheckedColor' DataItem='NumberControlTest.Controls.NumberControl'它表明它正在尝试在用户控件本身中查找BackCheckedColor。 That does not make sense to me. 这对我来说没有意义。 Can somebody help?? 有人可以帮忙吗?

User Control Xaml 用户控制Xaml

<UserControl.Resources>        
    <local:CheckedToBrushConverter x:Key="CheckedToBrushConverter" 
                                   CheckedBackgroundColor="{Binding CheckedBackgroundColor}"
                                   CheckedForegroundColor="{Binding CheckedForegroundColor}"
                                   UncheckedBackgroundColor="{Binding UncheckedBackgroundColor}"
                                   UncheckedForegroundColor="{Binding UncheckedForegroundColor}"/>
</UserControl.Resources>
<Grid Tapped="Grid_Tapped">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="16*"/>
        <ColumnDefinition Width="130*"/>
        <ColumnDefinition Width="16*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="16*"/>
        <RowDefinition Height="130*"/>
        <RowDefinition Height="30*"/>
    </Grid.RowDefinitions>

    <Ellipse x:Name="Ellipse" Grid.RowSpan="3" Grid.ColumnSpan="3" Fill="{Binding IsChecked, Converter={StaticResource CheckedToBrushConverter}, ConverterParameter=background}"/>
    <Viewbox Grid.Row="1" Grid.Column="1">
        <TextBlock x:Name="NumberBlock" TextWrapping="Wrap" FontFamily="Segoe UI" Text="{Binding NumberValue}" Foreground="{Binding IsChecked, Converter={StaticResource CheckedToBrushConverter}, ConverterParameter=foreground}" />        
    </Viewbox>

</Grid>

User control code behind 用户控制码后面

 public sealed partial class NumberControl : UserControl
{
    public NumberControl()
    {
        this.InitializeComponent();
        this.DataContext = this;
    }

    public string UncheckedBackgroundColor
    {
        get { return (string)GetValue(UncheckedBackgroundColorProperty); }
        set { SetValue(UncheckedBackgroundColorProperty, value); }
    }

    // Using a DependencyProperty as the backing store for UncheckedBackgroundColor.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UncheckedBackgroundColorProperty =
        DependencyProperty.Register("UncheckedBackgroundColor", typeof(string), typeof(NumberControl), new PropertyMetadata(string.Empty));


    public string CheckedBackgroundColor
    {
        get { return (string)GetValue(CheckedBackgroundColorProperty); }
        set { SetValue(CheckedBackgroundColorProperty, value); }
    }

    // Using a DependencyProperty as the backing store for CheckedBackgroundColor.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CheckedBackgroundColorProperty =
        DependencyProperty.Register("CheckedBackgroundColor", typeof(string), typeof(NumberControl), new PropertyMetadata(string.Empty));

plus more dependency properties like those. 以及更多类似的依赖项属性。

MainPage xaml 主页xaml

<Page.Resources>
    <DataTemplate x:Key="NumberTemplate">
        <Grid>
            <controls:NumberControl 
                UncheckedBackgroundColor="{Binding BackUncheckedColor}"
                UncheckedForegroundColor="{Binding ForeUncheckedColor}"
                CheckedBackgroundColor="{Binding BackCheckedColor}"
                CheckedForegroundColor="{Binding ForeCheckedColor}"
                NumberValue="{Binding Value}" 
                IsChecked="{Binding IsChecked}"
                HorizontalAlignment="Center" 
                VerticalAlignment="Center" Width="45" Height="45"/>
        </Grid>
    </DataTemplate>
</Page.Resources>

<Grid Background="#0f455f">
    <GridView x:Name="NumbersGridView" ItemTemplate="{StaticResource NumberTemplate}" ItemsSource="{Binding Numbers, Mode=TwoWay}"/>
    <Button x:Name="printButton" Content="Print" VerticalAlignment="Bottom" HorizontalAlignment="Center" Click="printButton_Click"/>
</Grid>

Model class which provides the data of the collection bound to the gridview 模型类,提供绑定到gridview的集合的数据

public class MockNumber
{
    public MockNumber(bool isChecked, int value, string backchcolor, string forchcolor, string backunchcolor, string forunchcolor)
    {
        IsChecked = isChecked;
        Value = value;
        BackCheckedColor = backchcolor;
        ForeCheckedColor = forchcolor;
        BackUncheckedColor = backunchcolor;
        ForeUncheckedColor = forunchcolor;
    }

    public bool IsChecked { get; set; }
    public int Value { get; set; }
    public string BackCheckedColor { get; set; }
    public string ForeCheckedColor { get; set; }
    public string BackUncheckedColor { get; set; }
    public string ForeUncheckedColor { get; set; }
}

EDIT: How the model is instantiated and bound in the MainPage codebehind. 编辑:如何实例化模型,并在后面的MainPage代码中绑定。

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

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        makelist();
    }

    void makelist()
    {
        for (int i = 1; i <= 20; i++)
        {
            Numbers.Add(new MockNumber(i % 4 == 0 ? true : false, i, "#dead2b", "#000000", "#dead2b", "#f0b60c"));
        }
    }

    private ObservableCollection<MockNumber> numbers = new ObservableCollection<MockNumber>();
    public ObservableCollection<MockNumber> Numbers
    {
        get
        {
            return numbers;
        }
        set
        {
            numbers = value;
        }
    }

The reason why it's trying to find the 'BackCheckedColor' property from the NumberControl is because you set the user control's datacontext to itself. 它试图从NumberControl中查找“ BackCheckedColor”属性的原因是因为您将用户控件的datacontext设置为其自身。

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

You're telling the user control that your data context is itself. 您是在告诉用户控件您的数据上下文本身就是它。 It means that when you do the "{Binding}" the path should be a property of the user control which I don't think is a good idea. 这意味着当您执行“ {Binding}”时,路径应该是用户控件的属性,我认为这不是一个好主意。

I understand that you want to bind some dependency properties to your Model class but I didn't see in your example where you instantiated the model class and use it as your data context. 我知道您想将某些依赖项属性绑定到您的Model类,但是在您的示例中没有看到您实例化模型类并将其用作数据上下文的情况。

Another thing to consider, you might want to use a custom control instead of a user control. 要考虑的另一件事,您可能想使用自定义控件而不是用户控件。 I can see that you added some dependency properties to your user control but in practice, dependency properties added to custom controls and static classes that has attached properties. 我可以看到您向用户控件中添加了一些依赖项属性,但实际上,依赖项属性已添加到自定义控件和具有附加属性的静态类中。

EDIT: After reading your additional code, I can see that the user control's datacontext was being set to 'this' which is itself. 编辑:阅读您的其他代码后,我可以看到用户控件的datacontext被设置为本身的'this'。 You need to remove that. 您需要删除它。

public sealed partial class NumberControl : UserControl
{
    public NumberControl()
    {
        this.InitializeComponent();
        this.DataContext = this; //Remove this line 
    }
//...

Then after removing that, you usercontrol should inherit the GridViewItem's Binding or you can explicitly put the datacontext in your DataTemplate. 然后,将其删除后,用户控件应该继承GridViewItem的Binding,或者可以将datacontext显式放入DataTemplate中。

<DataTemplate x:Key="NumberTemplate">
    <Grid>
        <controls:NumberControl DataContext="{Binding}" <!--specify the data context-->
            UncheckedBackgroundColor="{Binding BackUncheckedColor}"
//..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM