【问题标题】:How to update ListBox using INotifyPropertyChanged如何使用 INotifyPropertyChanged 更新 ListBox
【发布时间】:2011-11-09 13:34:14
【问题描述】:

我有一个日历,并且我在日历项控件中嵌套了一个项控件,以便我可以在网格单元(日期)中显示我想要为其创建事件的事件。日历为 7 列和 6 行。现在我只是使用一个列表框来实际显示事件(标题)。我可以在启动时添加项目,但我希望能够在程序已经运行后添加/删除/更改。我以前尝试过 INotifyPropertyChanged 一次,但我一生都无法弄清楚。如果有人可以拿走我所拥有的东西并给我看或给我一些关于如何做到这一点的提示,我将非常感激。

我可以在启动前添加(项目)的类:

public class eventProperties : ObservableCollection<eventsTitles>
{
    //public string Eventer { get; set; }

    public eventProperties() : base() 
    {
        Add(new eventsTitles("First Test"));
        Add(new eventsTitles("First Test#2"));

    }

这是一个窗口(类),当我想在程序启动并运行后添加一个事件时弹出。我需要弄清楚如何使用此窗口添加项目以及如何将其添加到某个日期(网格单元)

    public Event(MainWindow parentform)
    {

        InitializeComponent();
        _parentForm = parentform;
        //this.month = month;
        //this.day = day;
        //this.year = year;
        lblCreateEvent.Content = "Create Event For " + month + " / " + day + " / " + year;

    }

    private void btnSubmit_Click(object sender, RoutedEventArgs e)
    {
        month = Convert.ToInt32(txtMonth.Text);
        day = Convert.ToInt32(txtDay.Text);
        year = Convert.ToInt32(txtYear.Text);



        Schedule sched = new Schedule();
        DateTime curr = DateTime.Now;
        int[] m = new int[7];
        DateTime newcurr = new DateTime(year, month, day);

        var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
        var ms = cal.GetWeekOfYear(new DateTime(newcurr.Year, newcurr.Month, 1), System.Globalization.CalendarWeekRule.FirstDay, System.DayOfWeek.Sunday);

           // for (var i = 1; newcurr.Month == 11; newcurr = newcurr.AddDays(1))
           // {

                var month_week = (newcurr.Day / 7);
                sched.MonthWeek = newcurr.GetWeekOfMonth().ToString();
                sched.Month = newcurr.Month.ToString();
                sched.Year = newcurr.Year.ToString();
                sched.day = newcurr.Day.ToString();
                sched.WeekOfYear = cal.GetWeekOfYear(newcurr, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString();
                sched.dayofweek = newcurr.DayOfWeek.ToString();


                //Here is where the calender is created. By looping through all the days in the selected month it will find the weeknumber and day of the week -->
                // that that particular date belongs to and place in the correct gridcell.
                _parentForm.bindings.schedule.Add(new Schedule { WeekNo = newcurr.GetWeekOfMonth() - 1, WeekDay = (int)newcurr.DayOfWeek, day = newcurr.Day.ToString(), eventTitle = "Camper Calender"    });

这是我需要绑定所有内容的实际日历 XAML。

     </customgridcontrol:GridControl>


     </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <Button Content="{Binding day}" Width="175" HorizontalAlignment="Stretch" VerticalAlignment="Top" VerticalContentAlignment="Top" HorizontalContentAlignment="Left" Name="btnCalenderDate" Click="btnCalenderDate_Click" Loaded="btnCalenderDate_Loaded" Height="18" FontSize="10" FontWeight="Bold">
                        </Button>

                        <ItemsControl  Height="60" VerticalAlignment="Stretch">
                            <ItemsControl.Resources>
                                <src:eventProperties x:Key="dataList"/>
                            </ItemsControl.Resources>
                            <ItemsControl.Items>
                                <ListBox ItemsSource="{Binding Source= {StaticResource dataList} }" DisplayMemberPath="EventTitle" VerticalAlignment="Top" IsSynchronizedWithCurrentItem="True">            
                                </ListBox>
                            </ItemsControl.Items>
                        </ItemsControl>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
     <!-- ItemContainerStyle -->
        <ItemsControl.ItemContainerStyle>

            <Style >        
                    <Setter Property="Grid.Column" Value="{Binding WeekDay}"  />
                <Setter Property="Grid.Row" Value="{Binding WeekNo}" />
            </Style>
            </ItemsControl.ItemContainerStyle>
    </ItemsControl>

eventTitles 类

  namespace Camp_
  {
       public class eventsTitles
       {
            public string eventTitle {get; set;} 

            public eventsTitles()//String ev)
            {
               // this.eventTitle = ev;
            }

            public string EventTitle
            {
                get { return eventTitle; }
                set { eventTitle = value; }
            }
       }        
  }

【问题讨论】:

  • 你能告诉我们eventsTitles类的实现吗,那部分是为了正确回答...
  • 为什么要创建一个继承自ObservableCollection 的类?为什么不在day 类上添加一个ObservableCollection&lt;eventTitle&gt; 类型的属性?
  • @Rachel 我在这里看到了很多,但一直不明白人们为什么这样做。我只能假设在示例中某处有一个教程可以做到这一点
  • 有,我从 msdn 获得了示例。 msdn.microsoft.com/en-us/library/…

标签: c# wpf visual-studio inotifypropertychanged


【解决方案1】:

Harsh's answer 对于您实现INotifyPropertyChanged 的方式是正确的,但是您只需要为单个属性实现它。如果您希望通知 UI 集合已更改,请使用 ObservableCollection

因此,如果您有一个包含 Event.EventTitle 的标签,并且您想更改代码隐藏中的 EventTitle,您将在 EventClass 上实现 INotifyPropertyChanged,这样当您更新 myEvent.EventTitle 时,标签在 UI 中会自动更新为新值。

如果您有一个 ListBox(或 ItemsControl),当您在 Collection 中添加或删除项目时,您希望自动更新它,只需将 ListBox 绑定到 ObservableCollection 属性,它会自动更新 UI项目被添加或从中删除。

例如,

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <StackPanel>
         <Button Content="{Binding day}" Click="AddEvent" />

         <ItemsControl Height="60" ItemsSource="{Binding Events}">
             <ItemsControl.ItemTemplate>
                 <DataTemplate>
                    <TextBlock Text="{Binding EventTitle}" />
                 <DataTemplate>
             </ItemsControl.ItemTemplate>
         </ItemsControl>
        </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>

在此示例中,您的 Schedule 类将有一个名为 Events 的属性,它是一个 ObservableCollection&lt;Event&gt;。要添加新事件,您可以使用以下内容:

void AddEvent(object sender, EventArgs e)
{
    // Get the DataContext for the Button, which should be of type Schedule
    Schedule day = (sender as Button).DataContext as Schedule;

    // Add New Event. Since this is an ObservableCollection, UI will automatically update
    day.Events.Add(new Event { EventTitle = "Test Event" });
}

作为旁注,您应该查看一些.Net naming conventions

【讨论】:

  • 我收到一个错误,因为 Button 说没有找到命名空间或定义。 (发件人为“按钮”)。任何想法
  • @TMan 你需要导入命名空间System.Windows.Controls
  • 好吧,我有一个简单的问题。我有一个 schedule.cs,它只有 ObservableCollection 的属性,然后我有一个 schedulePage.xaml.cs,这是显示日历的页面,我将所有 xaml 信息放在其中。但是 schedulePage.xaml.cs 中的第一个 itemscontrol(calender) 绑定到 schedule.cs,所以你告诉我的所有内容都应该放在 schedule.cs 或 schedulePage.xaml.cs 中,我尝试了 schedulePage,当我点击按钮时它显示一个窗口必须是树的根。另外我的事件类也是一个解释错误的窗口,我应该制作一个单独的 event.cs 吗?
  • @TMan 不知道我明白你在问什么,但是是的,你应该有一个单独的 Event.cs 用于 Event 类,其中包含特定于 Event 的属性(名称,描述、日期等)
  • 那 Event.cs 应该是我用于 observableCollection 的吧?
【解决方案2】:

我认为eventTitles 一定有一些问题没有实现INotifyPropertyChanged 接口所以这里是实现的细节。

假设 eventTitles 类

public class eventTitles : INotifyPropertyChanged
{
    private string _eventtitle = string.Empty;

    public string EventTitle
    {
       get {return _eventtitle;}

        set
        {
            if (value != _eventtitle)
            {
                _eventtitle = value;
                NotifyPropertyChanged("EventTitle");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

如需进一步参考,您可以查看MSDN Post

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    • 2014-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多