非常简单的silverlight绑定无法正常工作

时间:2013-07-10 03:09:22

标签: silverlight binding

这应该是一个非常简单的解决方案,但是通过互联网搜索似乎有多种不同的方式来进行绑定,而NONE似乎确实有效。

我用按钮,文本框和列表框创建了一个简单的应用程序。用户在文本框中添加文本,单击“添加”,我希望文本显示在列表框中。请注意,“添加”按钮将创建一个Person,其首字符为文本框中的文本,并且姓氏为“Jones”。这只是为了弄清楚如何绑定到实际工作。我有ObservableCollection但似乎无法弄清楚如何将资源放入类本身的对象中。这甚至可能吗?我是否必须创建一个单独的类来进行绑定?

这是完整的XMAL

<UserControl x:Class="simpleBinding.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:z="clr-namespace:simpleBinding"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Canvas x:Name="LayoutRoot" Background="White">
    <Button Name="_b"  Content="Add" Height="23" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="58" Canvas.Left="90" Canvas.Top="5" Click="OnAdd" />
    <TextBox Name="_tb" Canvas.Left="12" Canvas.Top="4" Height="24" Width="72"></TextBox>
    <ListBox Name="_list" Canvas.Left="18" Canvas.Top="41" Height="98" Width="190" />
</Canvas>

这里是完整的代码

namespace simpleBinding
{
    public partial class MainPage : UserControl
    {
        public ObservableCollection<Person> PersonList = new ObservableCollection<Person>    ();
        public MainPage()
        {
            InitializeComponent();
        }

        private void OnAdd(object sender, RoutedEventArgs e)
        {
            PersonList.Add(new Person(_tb.Text, "Jones"));
        }
    }

    public class Person
    {
        public string FirstName {private set; get;}
        public string LastName {private set; get; }

        public Person(string fName, string lName)
    {
            FirstName = fName;
        LastName = lName;
    }
    }
}

感谢您的帮助, 克里斯

2 个答案:

答案 0 :(得分:2)

说明Ravuthasamy&amp; aqwert的评论。您必须先设置DataContext。您可以在this中设置DataContext或阅读MVVM的工作方式(这是一个很好的Silvelight绑定模式):

<强> c#中

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

将类属性绑定到元素之后:

<强>的Xaml

<ListBox
    ItemsSource="{Binding PersonList}"
    Canvas.Left="18"
    Canvas.Top="41"
    Height="98"
    Width="190" />

答案 1 :(得分:1)

按照时间表,您可以看到我花了一周的时间才终于找到解决方案。我现在在这里张贴,希望别人不会浪费这么多时间。似乎有很多关于如何处理这个问题的帖子,这些例子是有限的。它们要么只显示C#,要么显示Xaml。然后在一个例子中不处理CollectionChanged和PropertyChanged。

这是一个简单的例子,它实现了集合更改和属性更改。以及Xaml中的绑定

这是Xaml。

<UserControl x:Class="simpleBinding.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:src="clr-namespace:simpleBinding"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">

<Canvas x:Name="LayoutRoot" Background="White" DataContext="{Binding}">
    <Canvas.Resources>
        <src:PersonList x:Key="myDataSource"></src:PersonList>
    </Canvas.Resources>

    <Button Name="_b"  Content="Add" Height="23" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="58" Canvas.Left="90" Canvas.Top="5" Click="OnAdd" />
    <Button Canvas.Left="150" Canvas.Top="5" Content="Edit" Height="23" Name="button1" Width="58" Click="OnEdit" />
    <TextBox Name="_tb" Canvas.Left="12" Canvas.Top="4" Height="24" Width="72"></TextBox>
    <ListBox Name="_list" Canvas.Left="18" Canvas.Top="41" Height="98" Width="190" ItemsSource="{Binding Source={StaticResource myDataSource}}" >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=FirstName}" Margin="0,0,2,0" />
                    <TextBlock Text="{Binding Path=LastName}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

</Canvas>

  1. 添加一个将引用您的代码的xmlns。在这种情况下,我的命名空间是xmlns:src,那么你可以使用VS intellisense转到正确的类。
  2. 将资源添加到layoutRoot项目。在我的情况下,我使用的是画布,但它可能是Grid或Stackpanel等。
  3. 声明资源后,您现在可以在ListBox中设置ItemSource绑定。
  4. 我选择使用模板来显示我认为非常酷的数据(Xaml的最佳部分!)在这种情况下有两个textBlock但如果我的基础数据源有图像,我可以使用这个很好地以图形方式显示数据。可以设置每个文本框的绑定,因为对象的公开属性是在C#代码中声明的。这将在下面讨论
  5. C#代码背后

    namespace simpleBinding
    {
    public partial class MainPage : UserControl
    {
        public PersonList m_pList = new PersonList();
    
        public MainPage()
        {
            InitializeComponent();
            _list.ItemsSource = m_pList;
            m_pList.Add(new Person("John", "Doe"));
    
        }
    
        private void OnAdd(object sender, RoutedEventArgs e)
        {
            m_pList.Add(new Person("Jones", _tb.Text));
    
        }
    
        private void OnEdit(object sender, RoutedEventArgs e)
        {
            m_pList[1].FirstName = _tb.Text;
        }
    }
    
    public class PersonList : ObservableCollection<Person> , INotifyPropertyChanged
    {
        public PersonList() : base()    // need to call  base on intialization otherwise the binded resource is not updated.
        {
            Add(new Person("Willa", "Cather"));
            Add(new Person("Isak", "Dinesen"));
            Add(new Person("Victor", "Hugo"));
            Add(new Person("Jules", "Verne"));
    
    
        }
    
    }
    
    public class Person : INotifyPropertyChanged
    {
        private string _fName;
        private string _lName;
    
        public event PropertyChangedEventHandler PropertyChanged;
    
    
    
        public string FirstName
        {
            set
            {
                _fName = value;
                NotifyPropertyChanged("FirstName");
            }
            get
            {
                return _fName;
            }
        }
        public string LastName
        {
            set
            {
                _lName = value;
                NotifyPropertyChanged("LastName");
            }
            get
            {
                return _lName;
            }
        }
    
    
    
        public Person(string fName, string lName) : base()
        {
            FirstName = fName;
            LastName = lName;
        }
    
        public override string ToString()
        {
            return String.Format("{0} {1}", FirstName, LastName);
        }
    
    
        private void NotifyPropertyChanged(String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
    
    }
    

    }

    我选择使用ObservableCollection,因为它实现了INotifyCollectionChanged。公开变量,允许您绑定到Xaml中声明的资源。 (更好的代码,使var变为私有,并具有通过get公开变量的属性!)

    1. ListBox _List需要在Code Behind中设置其ItemsSource属性!没有这个,每当你更改列表(添加,删除等)时,UI都不会更新。 AND 实际上你根本不需要ListBox中的绑定,因为我们在Code中设置源代码很不错,但是在具有这个绑定控件的设计器中你可以看到绑定工作正常因为在实例化PersonList时添加了四个名称。
    2. ObservableCollection需要添加INotifyCollectionChanged。如果没有这个,当更改属性时,UI不会更改。
    3. 要向UI公开的属性需要在ObservableCollection中包含的对象中实现(在我的情况下,Person类同时暴露FirstName和LastName),然后这些属性可以绑定在Xaml中(见textBlocks的)
    4. INotifyPropertyChanged要求您实现PropertyChanged事件,即公共事件PropertyChangedEventHandler PropertyChanged;
    5. 要实际触发该事件,“Person”对象需要实现代码来执行该操作,在我的例子中是NotifyPropertyChanged方法。每次设置一个属性时,我都会调用此方法,而该方法又会查看PropertyChanged事件是否为null,如果没有,则会引发该事件。
    6. 以下是属性更改的关键,在不向Observable集合添加INotifyPropertyChanged的情况下,PropertyChanged为null。
    7. 希望这有助于某人