WPF - 为列表框中的单个条目设置更改的事件处理程序

时间:2013-08-13 07:30:51

标签: c# wpf listbox listboxitem

在我的wpf应用程序中,我想为listbox条目编写更改的事件处理程序。此条目由组合框和TimePickers组成。我的列表框与某个网络帐户相关联,因此列表框的所有条目都保存在那里。当我尝试保存已编辑的条目时,将保存所有条目。为了避免这个问题,我想编写更改的事件处理程序,以便它只给我更新的条目。如何为仅编辑的条目而不是所有条目编写已更改的事件处理程序。

列表框的xaml:

<ListBox x:Name="listBox1" ItemsSource="{Binding}" Margin="0,131,0,59" ItemTemplateSelector="{StaticResource templateSelector}" SelectionMode="Single" SelectionChanged="listBox1_SelectionChanged">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <EventSetter Event="MouseDoubleClick" Handler="listBox1_MouseDoubleClick">
                    </EventSetter>
                </Style>
            </ListBox.ItemContainerStyle>
</ListBox>

ListBox在单个条目中包含以下内容 -

<StackPanel Orientation="Horizontal" Width="596">
                <TextBox Text="{Binding ClientNameBinding,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Background="Yellow" Padding="0" Margin="0" BorderThickness="0" TextWrapping="Wrap" Width="145"/>
                <TextBox Text="{Binding ApplicationNameBinding}" Background="Yellow" Padding="0" Margin="0" BorderThickness="0" TextWrapping="Wrap" Width="90"/>
                <xctk:TimePicker Name="StartPicker" Value="{Binding StartValue, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Format="Custom" FormatString="hh:mm tt" Background="Yellow" Padding="0" Margin="0" BorderThickness="0" Width="100" EndTime="11:59:0"/>
                <xctk:TimePicker Name="EndPicker" Value="{Binding EndValue, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" Format="Custom" FormatString="hh:mm tt" Background="Yellow" Padding="0" Margin="0" BorderThickness="0" Width="60" EndTime="11:59:0"/>
                <TextBox Text="{Binding TaskNameBinding}" Background="Yellow" Padding="0" Margin="0" BorderThickness="0" TextWrapping="Wrap" Width="71"/>
                <ComboBox x:Name="ProjectComboBox" ItemsSource="{Binding Path=projectList, ElementName=MainWin}" SelectedValuePath="_id" DisplayMemberPath="_name"  SelectedItem="{Binding ProjectNameBindingClass, Mode=OneWayToSource}" Width="130" Background="Yellow" BorderThickness="0"/>
</StackPanel>

1 个答案:

答案 0 :(得分:0)

通常的做法是保留一个标志,表明数据是否有任何变化。 MVVM样式的样本可能是这样的:

1)基础视图模型,它实现INotifyPropertyChanged

public abstract class ViewModel : INotifyPropertyChanged
{
    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

2)列表条目的视图模型。请注意,这是HasChanges属性。当任何其他视图绑定属性发生更改时,HasChanges变为true

public class MyListEntryViewModel : ViewModel
{        
    public string ClientName
    {
        get { return clientName; }
        set
        {
            if (clientName != value)
            {
                clientName = value;
                OnPropertyChanged("ClientName");
            }
        }
    }
    private string clientName;

    // the rest of bindable properties (ApplicationName, StartPicker, etc.)

    public bool HasChanges
    {
        get { return hasChanges; }
        set
        {
            if (hasChanges != value)
            {
                hasChanges = value;
                OnPropertyChanged("HasChanges");
            }
        }
    }
    private bool hasChanges;

    protected override void OnPropertyChanged(string propertyName)
    {
        base.OnPropertyChanged(propertyName);

        if (propertyName != "HasChanges")
        {
            HasChanges = true;
        }
    }
}

3)编辑器的视图模型(用于保存列表条目的内容以及用于添加,删除,保存等的命令):

public class MyEditorViewModel : ViewModel
{
    private void SaveChanges()
    {
        var changedItems = Items
            .Where(item => item.HasChanges);

        // send changed items to server
    }

    private bool CanSaveChanges()
    {
        return Items.Any(item => item.HasChanges);
    }

    public MyEditorViewModel()
    {
        SaveChangesCommand = new RelayCommand(SaveChanges, CanSaveChanges);
    }

    public ObservableCollection<MyListEntryViewModel> Items
    {
        get
        {
            return items ?? (items = new ObservableCollection<MyListEntryViewModel>());
        }
    }
    private ObservableCollection<MyListEntryViewModel> items;

    public RelayCommand SaveChangesCommand { get; private set; }
}