用户控件上的数据绑定问题 [英] Issue with DataBinding on a UserControl

查看:79
本文介绍了用户控件上的数据绑定问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个非常基本的问题.
我已经创建了一个用户控件,例如这样的示例:

 <   UserControl     x:Class   ="  
 
          xmlns   ="  http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
          xmlns:x   ="  > 
    <  网格 > 
        <   TextBox     ="   txtMessage" 文本   {绑定消息,ElementName = root}" 宽度     高度  ="  >  <  /TextBox  > 
    <  /Grid  > 
<  /UserControl  >  



我创建了一个名为MessageDependencyProperty ,我想与DataBinding一起使用.该代码如下所示:

 公共 部分  class  txtItem:UserControl
{
公共 静态 只读 DependencyProperty MessageProperty = DependencyProperty.注册("  typeof ( 字符串), typeof (txtItem), UIPropertyMetadata(" ,textChangedCallback));
        私有 静态  void  textChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            txtItem输入=(txtItem)d;
            input.txtMessage.Text = e.NewValue  as   String ;
        }
        公共 字符串消息
        {
            获取 {返回(字符串)GetValue( MessageProperty); }
             set  {SetValue(MessageProperty, value ); }
        }
 } 



现在,一旦构建了控件,我就希望该控件能够与数据绑定一起使用,就像普通TextBox的工作方式一样.在我的窗口中,我将其用作:

 <   ListBox     x:Name   ="     ItemsSource   ="  {绑定}" <   ListBox.ItemTemplate  > 
               <   DataTemplate  > 
                   <   StackPanel     ="  <   TextBlock     ="   {Binding Name}" / <   local:txtItem    水平对齐  ="  垂直对齐  中心"    ="     ="   {绑定值}" > 
                   <  /StackPanel  > 
               <  /DataTemplate  > 
           <  /ListBox.ItemTemplate  > 
       <  /ListBox  >  




从后面的代码中:
私人List< Element> items = null;

 私有 无效 Window_Loaded(对象发​​件人,RoutedEventArgs e)
        {
             .items = 列表< Element>();
            items.Add(元素{名称= " ,值= " });
             .lstBox.DataContext =项目;
        } 



Element类也可以从INotifyPropertyChanged实现:

  public   class 元素:INotifyPropertyChanged
    {
        私有 字符串 _Name;
        公共 字符串名称
        {
            获取
            {
                返回 .
            }
            设置
            {
                ._Name =  .OnPropertyChanged(" ) ;
            }
        }
        私有 字符串 _Value;
        公共 字符串值
        {
            获取
            {
                返回  ._ Value;
            }
            设置
            {
                ._Value =  .OnPropertyChanged(" ) ;
            }
        }

         #region INotifyPropertyChanged成员
 公共 虚拟 无效 OnPropertyChanged (字符串信息)
        {
            如果(.PropertyChanged!=  )
                 .PropertyChanged( PropertyChangedEventArgs (信息));
        }
        公共 事件 PropertyChangedEventHandler PropertyChanged;
         #endregion
} 




现在,当我更改UserControl内的Textbox 内的数据时,它不会更新实际对象.我什至从INotifyPropertyChanged实现了UserControl ,并在TextBox上的值更改时调用了该事件,但是but,它对我没有用.谁能在这方面帮助我.

如果您想查看代码,可以从这里下载:
TextCalc.zip(80 KB)

解决方案

Hey Abhishek,

你错过了什么.通常,您的代码应该可以工作,但是有一个小错误.这是代码:

 <   ListBox     x:Name   ="  
                    ItemsSource    {Binding}" <   ListBox.ItemTemplate  > 
        <   DataTemplate  > 
            <   StackPanel     ="  <   TextBlock     ="   {Binding Path = Name}"   / > 
                <   local:txtItem    水平对齐  ="                                                       VerticalAlignment   中心"  
                                                     宽度  ="                                                      消息  ="  > 
            <  /StackPanel  > 
        <  /DataTemplate  > 
    <  /ListBox.ItemTemplate  > 
<  /ListBox  > 



您的第一个错误是在这里:

 <   local:txtItem    水平对齐  ="  
 
                                                                    ="  中心" 
                                                                    ="   50" 
                                                                    ="   {绑定值,模式= TwoWay,UpdateSourceTrigger = PropertyChanged}" >  



您没有为双向模式绑定它. :(

第二个错误是您的UserControl.同样,绑定不正确.这是代码:

<UserControl x:Name="userControl" x:Class="TextCalc.txtItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <TextBox Name="txtMessage" Text="{Binding Message, ElementName=userControl, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="30" Height="20"></TextBox>
    </Grid>
</UserControl>



让我知道是否可以解决您的问题.如果它能解决您的查询,请不要忘记标记为答案".

谢谢&问候,
Kunal


尝试创建ObservableCollection类型的对象.
然后,您用实际数据值填充此对象并将其绑定到您的listbox.

public ObservableCollection<<Element>> MyCollection
{
    get
    {
        return this._myCollection;
    }
    set
    {
        this._Value = value;
        this.OnPropertyChanged("MyCollection");
    }
}



注意:我必须使用两个<<>>对于上面的Element类,好像我没有使用它.

<listbox x:name="lstBox" itemssource="{Binding <b>MyCollection</b>}" xmlns:x="#unknown">
           <listbox.itemtemplate>
               <datatemplate>
                   <stackpanel orientation="Horizontal">
                       <textblock text="{Binding Name}" />
                       <local:txtitem horizontalalignment="Center" verticalalignment="Center" width="50" message="{Binding Value}" xmlns:local="#unknown" />
                   </stackpanel>
               </datatemplate>
           </listbox.itemtemplate>
       </listbox>



列表框和文本框的绑定不同,因为列表框绑定到itemssource集合.

举个简单的例子,在此处.


I am in a very basic problem.
I have created a user control, say sample like this :

<UserControl x:Class="TextCalc.txtItem"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <TextBox Name="txtMessage" Text="{Binding Message, ElementName=root}" Width="30" Height="20"></TextBox>
    </Grid>
</UserControl>



I have created a DependencyProperty named Message which I want to work with DataBinding. The Code looks like :

public partial class txtItem : UserControl
{
public static readonly DependencyProperty MessageProperty = DependencyProperty.Register("Message",typeof(String),typeof(txtItem), new UIPropertyMetadata("0", textChangedCallback));
        private static void textChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            txtItem input = (txtItem)d;
            input.txtMessage.Text = e.NewValue as String;
        }
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }
 }



Now once I built the control, I want this control to work with Databinding just like how normal TextBox works. In my Window, I used this as :

<ListBox x:Name="lstBox" ItemsSource="{Binding}">
           <ListBox.ItemTemplate>
               <DataTemplate>
                   <StackPanel Orientation="Horizontal">
                       <TextBlock Text="{Binding Name}" />
                       <local:txtItem HorizontalAlignment="Center" VerticalAlignment="Center"  Width="50" Message="{Binding Value}"/>
                   </StackPanel>
               </DataTemplate>
           </ListBox.ItemTemplate>
       </ListBox>




From the codebehind :
private List<Element> items = null;

private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.items = new List<Element>();
            items.Add(new Element { Name = "Abhishek", Value = "300" });
            this.lstBox.DataContext = items;
        }



The Element class is also implemented from INotifyPropertyChanged :

public class Element : INotifyPropertyChanged
    {
        private string _Name;
        public string Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                this._Name = value;
                this.OnPropertyChanged("Name");
            }
        }
        private string _Value;
        public string Value
        {
            get
            {
                return this._Value;
            }
            set
            {
                this._Value = value;
                this.OnPropertyChanged("Value");
            }
        }

        #region INotifyPropertyChanged Members
        public virtual void OnPropertyChanged(string info)
        {
            if(this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
    }




Now when I change the data within the Textbox that comes within the UserControl, it doesnt update the actual object. I have even implemented the UserControl from INotifyPropertyChanged, and invoked the event when the value is changed on the TextBox, but alas, it didnt worked for me. Can anyone help me in this regard.

If you want to see the code you can download from here:
TextCalc.zip (80 KB)

解决方案

Hey Abhishek,

You missed something. Generally your code should work but there was a small mistake. Here is the code:

<ListBox x:Name="lstBox"
         ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Name}" />
                <local:txtItem HorizontalAlignment="Center"
                               VerticalAlignment="Center"
                               Width="50"
                               Message="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>



Your first mistake was here:

<local:txtItem HorizontalAlignment="Center"

                                       VerticalAlignment="Center"

                                       Width="50"

                                       Message="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>



You didn''t bind it for twoway mode. :(

Second mistake is in your UserControl. Samething, binding was not proper. Here is the code:

<UserControl x:Name="userControl" x:Class="TextCalc.txtItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <TextBox Name="txtMessage" Text="{Binding Message, ElementName=userControl, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="30" Height="20"></TextBox>
    </Grid>
</UserControl>



Let me know if it resolves your issue. Don''t forget to "Mark As Answer" if it resolves your query.

Thanks & Regards,
Kunal


Try by creating an object of type ObservableCollection.
You then fill this object with actual data values and bind it to your listbox.

public ObservableCollection<<Element>> MyCollection
{
    get
    {
        return this._myCollection;
    }
    set
    {
        this._Value = value;
        this.OnPropertyChanged("MyCollection");
    }
}



Note: I had to use two <<>> for the Element class above as if I used one it was not appearing.

<listbox x:name="lstBox" itemssource="{Binding <b>MyCollection</b>}" xmlns:x="#unknown">
           <listbox.itemtemplate>
               <datatemplate>
                   <stackpanel orientation="Horizontal">
                       <textblock text="{Binding Name}" />
                       <local:txtitem horizontalalignment="Center" verticalalignment="Center" width="50" message="{Binding Value}" xmlns:local="#unknown" />
                   </stackpanel>
               </datatemplate>
           </listbox.itemtemplate>
       </listbox>



Listbox and Textbox binding are different as ListBox binds to an itemssource collection.

For a simple example, have a look here.


这篇关于用户控件上的数据绑定问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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