Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
178 views
in Technique[技术] by (71.8m points)

c# - add a check with MessageBox when DataGrid is changed

I have a desktop app already released (so I'd appreciate an answer that keeps the changes and regression tests at a minimum) and I need to add a consistency check CanBeDeleted when the grid is changed.

<DataGrid AutoGenerateColumns="False" 
    ItemsSource="{Binding CurrentPosIn.PosInLocationsList}" 
    CanUserAddRows="{Binding UpdateEnabled}" CanUserDeleteRows="{Binding UpdateEnabled}" >

I'm using UpdateEnabled for something different (profile permissions) and I don't want to make the DataGrid read only either: I'd prefer (unless it is too complex) to see a blocking alert (a MessageBox) preventing changes.

What I've done till now is

  1. against MVVM, because I've put the alert in the Model (but I can accept this, if it makes the changes quick and simple)
  2. not working, because the second part (see below) of my changes produces an invalid operation exception

The ViewModel contains the following list

    [Association(ThisKey="Partita", OtherKey="Partita", CanBeNull=true, IsBackReference=true)]
    public ObservableCollection<Model.PosInLocation> posin_locations_list = new  ObservableCollection<Model.PosInLocation>(); 
    public ObservableCollection<PosInLocation> PosInLocationsList {
        get { return posin_locations_list; }
        set { 
            posin_locations_list = value;
            OnPropertyChanged( () => PosInLocationsList );
        }
    } 

and I'm adding the consistency check here

    string _storage;
    [Column(Name = "storage"), PrimaryKey]
    public string Storage {
        get { return _storage; }
        set { 
            if (this.loadedEF) {
                string validate_msg;
                if (!PurchasePosIn.CanBeDeleted(out validate_msg)) {
                    // against MVVM
                    MessageBox.Show(validate_msg, "Alert", MessageBoxButton.OK); 
                    OnPropertyChanged( () => Storage  );
                    return;
                }
                Persistence.MyContext.deletePosInLocation(this);
            }
            _storage = value;
            OnPropertyChanged( () => Storage  );
            if (this.loadedEF) {
                Persistence.MyContext.insertPosInLocation(this);
            }               
        }
    }

and here (second part)

    internal void posin_locations_list_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
    {                   
        string validate_msg;
        if (!CanBeDeleted(out validate_msg)) {
            // indirectly produces an invalid operation exception 
            MessageBox.Show(validate_msg, "Alert", MessageBoxButton.OK);
            return;
        }
        if (args.OldItems != null)
            foreach(var oldItem in args.OldItems) {
                if ( ((PosInLocation)oldItem).Partita != null)        
                    Persistence.MyContext.deletePosInLocation((PosInLocation)oldItem);              
            }       
        if (args.NewItems != null)
            foreach(var newItem in args.NewItems)
            {
                PosInLocation newPosInLocation = (PosInLocation)newItem;
                if ( newPosInLocation.Partita == null) {
                    newPosInLocation.Partita = this.Partita;
                    newPosInLocation.PurchasePosIn = this;
                    newPosInLocation.loadedEF = true;
                }
             }
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Maybe it's ugly (really, it's not so ugly: imho it's a nice MVVM approach, also applicable to modern mahapps.metro Dialogs), but now I'm setting

if (!CanBeDeleted(out validate_msg)) {
    PurchaseItem.MessageBoxText = validate_msg;

an invisible TextBox

    <TextBox Visibility="Hidden" Name="tb_message"
        Text="{Binding MessageBoxText}"
        TextChanged="TextBox_TextChanged"

where I'm dispatching the alert

    void TextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        string alert = tb_message.Text;
        if (alert != null && tb_message.Text.Length>0) {
            Dispatcher.BeginInvoke(
                (Action)(() => { 
                            MessageBox.Show(alert, "Alert", MessageBoxButton.OK);
                            tb_message.Text = "";
                         }));
        }
    }

Rolling back added/deleted items

I see a connection with this other question Prevent adding the new Item on ObservableCollection.CollectionChanged event, in my case I'd say that prevent deleting is even more important. I don't know if there are more updated answers than this one (Can I rollback collection changes on collection changed event? which appears wrong) about this topic.

While the PropertyChanged can be easily raised to rollback an item update, for the collection changes I've been forced to pass and reference the view dispatcher inside the CollectionChanged event

PurchaseItem.dispatcher.BeginInvoke((Action)(() => RollBack(args)));

to rollback the added/deleted items

    bool rollingBack = false;
    private void RollBack(NotifyCollectionChangedEventArgs args) {
            rollingBack = true;
            if (args.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (var element in args.OldItems) {
                    PosInLocationsList.Add((PosInLocation)element);
                }
            }
            if (args.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (var element in args.NewItems) {
                    PosInLocationsList.Remove((PosInLocation)element);
                }
            }
            rollingBack = false;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...