开发者

Inserting a new object into L2S table and databinding to it prior to SubmitChanges() in WPF

I'm just getting started with Linq-to-SQL and data binding in WPF, most of which works like a dream so far!

I've got (what I though was) a common scenario:

a) Query list of records from a table via datacontext and bind to the current user control

this.DataContext = db.ClientTypes;

b) Have the user see a bound ListView and some bound detail controls to make changes to the existing records, with a db.SubmitChanges(ConflictMode.FailOnFirstConflict); to push the changes back to the DB. No problem.

c) User wants to add a new record, so we:

ClientType ct = new ClientType();
ct.Description = "<new client t开发者_Go百科ype>";
db.ClientTypes.InsertOnSubmit(ct);

However at this point I dont want to call db.SubmitChanges as I want the user to be able to update the properties of the object (and even back out of the operation entirely), but I want them to be able to see the new record in the bound ListView control. Thinking I just needed to re-run the query:

ClientType ct = new ClientType();
ct.Description = "<new client type>";
db.ClientTypes.InsertOnSubmit(ct);

// Rebind the WPF list?
this.DataContext = db.ClientTypes;
listView1.SelectedItem = ct;
listView1.ScrollIntoView(ct);

However this doesn't work, the newly created record is not part of the returned list. I'm not sure if this is because of caching within L2S or if I'm just going about this the wrong way. Is there a better way to accomplish this?

Thanks.


Instead of setting your Control.DataContext = db.ClientTypes, store db.ClientTypes somewhere else and bind to an ObservableCollection that wraps it.

var somewhereElse = db.ClientTypes;
var toBind = new ObservableCollection<ClientType>(somewhereElse);
toBind.CollectionChanged += (object sender, NotifyCollectionChangedEventArgs e) =>
{
    if (e.Action == NotifyCollectionChangedAction.Add)
        types.InsertAllOnSubmit<AddressType>(e.NewItems.Cast<AddressType>());
};
this.DataContext = toBind;

Then, when the user wants to add a new item:

ObservableCollection<ClientType> toBind = this.DataContext as ObservableCollection<ClientType>;
System.Diagnostics.Debug.Assert(toBind != null);

ClientType ct = new ClientType();
ct.Description = "<new client type>";
toBind.Add((ct);

Calling toBind.Add will cause the CollectionChanged event handler above to call InsertOnSubmit on the original Table instance, so you can call SubmitChanges() when convenient. Obviously, you'd probably want to do the same with Remove ...

Hope that helps :)


It may be worth looking into the MVVM pattern. In MVVM you have a ViewModel which wraps your Model, so you would have a ClientTypeViewModel class.

public class ClientTypeViewModel : INotifyProperyChanged
{
    public ClientTypeViewModel(ClientType dataModel)
    {
        this.dataModel = dataModel;
    }

    public string Description
    {
        get { return this.dataModel.Description; }
        set 
        { 
            this.dataModel.Description = value; 
            // Raise PropertyChanged event
        }
    }

    private ClientType dataModel;
}

And something like an ApplicationView model, which would contain an ObservableCollection of ClientTypeViewModels.

public ApplicationViewModel
{
    public ObservableCollection<ClientTypeViewModel> ClientTypes { get; private set; }
}

You then bind to ApplicationViewModel.ClientTypes instead of the plain data model. This way, your view will be automatically updated whenever a new item is added to ClientTypes, or a property is changed on the ClientType view model. ApplicationViewModel can listen for changes on the ClientTypes collection and automatically add newly added items to the DataContext.

You may think it's overkill for your application, I don't know - but MVVM is definitely somthing worth learning. If it feels like you're struglling or fighting with WPF, MVVM is likely where to look ;)


Look at CreateBindingList.


I think it's just because you're assigning the same reference to the DataContext. Hence, WPF doesn't see the need to refresh the binding. The easiest way around this is to:

// rebind
this.DataContext = null;
this.DataContext = db.ClientTypes;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜