WPF。设置自定义控件的依赖项属性

时间:2014-05-22 19:45:30

标签: c# wpf user-controls dependency-properties

我知道有很多关于依赖属性的问题已经回答了,但是我读过的这些问题都没有解决我的问题所以这里有。

我有一个带有按钮和文本块的简单用户控件。文本块包含一个我希望能够从包含控件的窗口或视图设置的数字。我还需要通过按下控件中的按钮来增加值。

这是我的主窗口:

    <Window x:Class="DependencyPropertiesTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:local="clr-namespace:DependencyPropertiesTest">
    <Grid>
        <StackPanel Width="200" VerticalAlignment="Center">
            <local:UserControl1 Margin="10" UserControlNumber="{Binding Number}"/>
            <TextBlock Text="{Binding Number}" Margin="10"/>
            <Button Content="n" Click="Button_Click" Margin="10"/>
        </StackPanel>
    </Grid>
</Window>

背后的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DependencyPropertiesTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            Number = 1;
        }

        private int number;
        public int Number
        {
            get { return number; }
            set
            {
                number = value;
                OnPropertyChanged("Number");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Number++;
        }
    }
}

这是我的自定义控件:

    <UserControl x:Class="DependencyPropertiesTest.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">
    <Grid>
        <Viewbox HorizontalAlignment="Center" VerticalAlignment="Center" Height="40" Width="100">
            <Border BorderBrush="Black" BorderThickness="1">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding UserControlNumber, TargetNullValue='nn',  FallbackValue='ff'}" Margin="5"/>
                    <Button Content="+" Margin="5" Width="30" Click="Button_Click"/>
                </StackPanel>
            </Border>
        </Viewbox>

    </Grid>
</UserControl>

代码背后:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DependencyPropertiesTest
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class UserControl1 : UserControl, INotifyPropertyChanged
    {
        public UserControl1()
        {
            InitializeComponent();
            DataContext = this;
        }



        public int UserControlNumber
        {
            get { return (int)GetValue(UserControlNumberProperty); }
            set { SetValue(UserControlNumberProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UserControlNumber.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UserControlNumberProperty =
            DependencyProperty.Register("UserControlNumber", typeof(int), typeof(UserControl1), new PropertyMetadata(0));



        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            UserControlNumber++;
        }
    }
}

主窗口中的两个按钮应分别增加用户控件的文本块中的值,一个来自窗口,另一个来自控件本身。我可以将主窗口中的值设置为这样的文字:

<local:UserControl1 Margin="10" UserControlNumber="5"/>

但是当我尝试给它一个绑定值时,它不起作用。使用Snoop检查绑定会产生以下错误:

消息:无法设置表达式。它被标记为“不可共享”并且已被使用。

更新。

我现在尝试了这个,但它仍然无效:

        public int UserControlNumber
    {
        get { return (int)GetValue(UserControlNumberProperty); }
        set { SetValue(UserControlNumberProperty, value); }
    }

    // Using a DependencyProperty as the backing store for UserControlNumber.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UserControlNumberProperty =
        DependencyProperty.Register("UserControlNumber", typeof(int), typeof(UserControl1), new PropertyMetadata(0, TextBlockPropertyChanged));

    private static void TextBlockPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        UserControl1 uc1 = d as UserControl1;
        int newNumber = (int)e.NewValue;

        uc1.MyTextBlock.Text = newNumber.ToString();
    }

在主窗口中:

<local:UserControl1 Margin="10" UserControlNumber="{Binding Number, Mode=TwoWay}"/>

1 个答案:

答案 0 :(得分:0)

在你的Window Xaml中你可以在TwoWays模式中绑定:

<local:UserControl1 Margin="10" UserControlNumber="{Binding Number, Mode=TwoWays}"/>

否则在User控件内部,该值将增加,但窗口中的绑定将不会更改...使用TwoWays绑定时,窗口中的Number也将更改。