简体   繁体   中英

How to programmatically refresh wpf c#?

I have this scenario well, i'll let the model explain.

public class ScheduleMonthlyPerDayModel 
{
    public DateTime Date { get; set; }

    public string Day 
    { 
        get
        {
            return Date.Day.ToString();
        }
    }

    ObservableCollection<AppointmentDTO> _appointments;
    public ObservableCollection<AppointmentDTO> Appointments 
    {
        get
        {
            return _appointments;
        }
        set
        {
            _appointments = value;

            if (value.Count > 0)
                NotifyOfPropertyChange(() => HasSchedule);
        }
    }

    public bool BelongsToCurrentMonth
    {
        get;
        set;
    }

    public bool HasSchedule
    {
        get
        {
            return _appointments.Count > 0 ? true : false;
        }
    }

    public ScheduleMonthlyPerDayModel()
    {
        _appointments = new ObservableCollection<AppointmentDTO>();
    }

    public void ClearCollection()
    {
        _appointments.Clear();
    }
}

public class ScheduleMonthlyPerWeekModel
{
    public ScheduleMonthlyPerDayModel Sunday{get; set;}

    public ScheduleMonthlyPerDayModel Monday{get; set;}

    public ScheduleMonthlyPerDayModel Tuesday{get; set;}

    public ScheduleMonthlyPerDayModel Wednesday{get; set;}

    public ScheduleMonthlyPerDayModel Thursday{get; set;}

    public ScheduleMonthlyPerDayModel Friday{get; set;}

    public ScheduleMonthlyPerDayModel Saturday{get; set;}
}

The bindings to xaml are working with a glimpse of the xaml like this:

headereditemscontrol itemsSource= weekcollection , where weekcollection is an object of schedulemonthlyperweekmodel .

Inside that headereditemscontrol I have templated each day for each property of the schedulemonthlyperweekmodel as follows:

<Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"  Style="{StaticResource CalendarDates}" Text="{Binding Path=Saturday.Day}" />
<ListBox Grid.Row="1" Grid.ColumnSpan="2" Padding="0" 
         ItemsSource="{Binding Path= Saturday.Appointments}"
         ItemTemplate="{StaticResource myItemStyle}"
         Visibility="{Binding Path=Saturday.HasSchedule, Converter={StaticResource BoolToVisibilityConverter}}" />

Basically, I'm trying to achieve a monthly view with each day having a collection of appointments. My problem is that when I programmatically add items to the, for example here, saturday.appointments collection, through debug appending of items is a success and notifying the main collection(weekcollection), does not refresh the UI.

What I would like to achieve is: after I add the supposed appointment to its corresponding day/dates, the user interface will also update accordingly, but how do I do that?

Currently, the UI only updates if I change/toggle to different then back, after that the appointments are shown nicely. I would like to automate it, as it is ugly to require a user to toggle to something else then back before they can see the appointments list.

As Nick suggested, using the INotifyPropertyChanged interface is key.

http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx

If you want the ObsCollection to be aware of property changes, you have to implement this interface as displayed in the link above. This will update the UI control that it's bound to when something is added, removed or changed. Without it, you'd actually have to track the changes in code and update them manually.

It's actually really easy to implement and use and it's freaking AWESOME. If you don't want to use this, you may have well as just used a winform. =)

Hope this helps.

The problem with your Visibility is that it's binding to a readonly property which calculates a value on get . Therefore, there is no way for it to notify that it has changed.

Your HasSchedule property needs to know when the Appointment property changes. The setter for the Appointment property only knows when the entire list changes. In your case you need to know when the contents of the list changes.

ObservableCollection has an event which tells you when the contents of the list changes, called CollectionChanged . You should do the following to notify that your HasSchedule property has changed using this event:

ObservableCollection<AppointmentDTO> _appointments;
public ObservableCollection<AppointmentDTO> Appointments
{
    get
    {
        return _appointments;
    }
    set
    {
        if (_appointments != value)
        {
            if (_appointments != null)
                _appointments.CollectionChanged -= Appointments_CollectionChanged;

            _appointments = value;

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("HasSchedule"));

            if (_appointments != null)
                _appointments.CollectionChanged += Appointments_CollectionChanged;
        }
    }
}

void Appointments_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs("HasSchedule"));
}

This is assuming, as you have said, you have implemented INotifyPropertyChanged in your ViewModel. In this case, every time your collection changes in some way, it notifies that the HasSchedule property has changed. The binding will refresh the value and update the visibility if it has changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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