한 번에 하나의 접근 방식을 사용하고 있습니다. 첫 번째로, 나는 이것을 dicuss에 대한 참조 포인트를 보여줄 것이고, 나는 각 방법론을 지원하는 데 필요한 다양한 변화를 강조 할 것이다.
내 데모의 기초는 리소스의 단일 엔터티를 반환하는 인증 된 단일 도메인 서비스입니다. SelectedResource를 보유하기위한 4 개의 명령 (저장, 실행 취소, 추가 및 삭제)과 컬렉션 및 속성을 표시합니다.
2 다른 클래스가이 인터페이스를 구현합니다 (블렌딩의 경우 1, 프로덕션의 경우 1). 제작은 여기에서 논의 할 유일한 것입니다. GetMyResources 기능의 동작 (lo.Entities)주의 :
public class WorkProvider
{
static WorkContext workContext;
public WorkProvider()
{
if (workContext == null)
workContext = new WorkContext();
}
public void AddResource(Resource resource)
{
workContext.Resources.Add(resource);
}
public void DelResource(Resource resource)
{
workContext.Resources.Remove(resource);
}
public void UndoChanges()
{
workContext.RejectChanges();
}
public void SaveChanges(Action action)
{
workContext.SubmitChanges(so =>
{
if (so.HasError)
// Handle Error
throw so.Error;
else
action();
}, null);
}
public void GetMyResources(Action<IEnumerable<Resource>> action)
{
var query = workContext.GetResourcesQuery()
.Where(r => r.UserName == WebContext.Current.User.Name);
workContext.Load(query, LoadBehavior.MergeIntoCurrent, lo =>
{
if (lo.HasError)
// Handle Error
throw lo.Error;
else
action(lo.Entities);
}, null);
}
}
뷰 모델에서를, 나는 다음과 같은 구현을 가지고 :
public class HomeViewModel : ViewModelBase
{
WorkProvider workProvider;
public HomeViewModel()
{
workProvider = new WorkProvider();
}
// _Source is required when returning IEnumerable<T>
ObservableCollection<Resource> _Source;
public CollectionViewSource Resources { get; private set; }
void setupCollections()
{
Resources = new CollectionViewSource();
using (Resources.DeferRefresh())
{
_Source = new ObservableCollection<Resource>();
Resources.Source = _Source;
Resources.GroupDescriptions.Add(new PropertyGroupDescription("Title"));
Resources.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
Resources.SortDescriptions.Add(new SortDescription("Rate", ListSortDirection.Ascending));
}
}
void loadMyResources()
{
workProvider.GetMyResources(results =>
{
using (Resources.DeferRefresh())
{
// This is required when returning IEnumerable<T>
_Source.Clear();
foreach (var result in results)
{
if (!_Source.Contains(result))
_Source.Add(result);
}
}
});
}
Resource _SelectedResource;
public Resource SelectedResource
{
get { return _SelectedResource; }
set
{
if (_SelectedResource != value)
{
_SelectedResource = value;
RaisePropertyChanged("SelectedResource");
}
}
}
public RelayCommand CmdSave { get; private set; }
public RelayCommand CmdUndo { get; private set; }
public RelayCommand CmdAdd { get; private set; }
public RelayCommand CmdDelete { get; private set; }
void setupCommands()
{
CmdSave = new RelayCommand(() =>
{
workProvider.SaveChanges(() =>
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
System.Windows.MessageBox.Show("Saved");
});
});
});
CmdUndo = new RelayCommand(() =>
{
workProvider.UndoChanges();
// This is required when returning IEnumerable<T>
loadMyResources();
});
CmdAdd = new RelayCommand(() =>
{
Resource newResource = new Resource()
{
ResourceID = Guid.NewGuid(),
Rate = 125,
Title = "Staff",
UserName = "jsmith"
};
// This is required when returning IEnumerable<T>
_Source.Add(newResource);
workProvider.AddResource(newResource);
});
CmdDelete = new RelayCommand(() =>
{
// This is required when returning IEnumerable<T>
_Source.Remove(_SelectedResource);
workProvider.DelResource(_SelectedResource);
});
}
}
다음과 같이 WorkProvider 클래스를 변경 포함 할 대체 방법 (통지 반환되는 행동 (workContext.Resources) :
public void GetMyResources(Action<IEnumerable<Resource>> action)
{
var query = workContext.GetResourcesQuery()
.Where(r => r.UserName == WebContext.Current.User.Name);
workContext.Load(query, LoadBehavior.MergeIntoCurrent, lo =>
{
if (lo.HasError)
// Handle Error
throw lo.Error;
else
// Notice Changed Enumeration
action(workContext.Resources);
}, null);
}
그리고 뷰 모델에 대한 변경 사항은 다음과 같이합니다 (_Source ObservableCollectio의 제거를 알 수 있습니다 N)
public class HomeViewModel : ViewModelBase
{
WorkProvider workProvider;
public HomeViewModel()
{
workProvider = new WorkProvider();
}
public CollectionViewSource Resources { get; private set; }
void setupCollections()
{
Resources = new CollectionViewSource();
using (Resources.DeferRefresh())
{
Resources.Filter += (s,a) =>
{
a.Accepted = false;
if (s is Resource)
{
Resource res = s as Resource;
if (res.UserName == WebContext.Current.User.Name)
a.Accepted = true;
}
};
Resources.GroupDescriptions.Add(new PropertyGroupDescription("Title"));
Resources.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
Resources.SortDescriptions.Add(new SortDescription("Rate", ListSortDirection.Ascending));
}
}
void loadMyResources()
{
workProvider.GetMyResources(results =>
{
using (Resources.DeferRefresh())
{
Resources.Source = results;
}
});
}
Resource _SelectedResource;
public Resource SelectedResource
{
get { return _SelectedResource; }
set
{
if (_SelectedResource != value)
{
_SelectedResource = value;
RaisePropertyChanged("SelectedResource");
}
}
}
public RelayCommand CmdSave { get; private set; }
public RelayCommand CmdUndo { get; private set; }
public RelayCommand CmdAdd { get; private set; }
public RelayCommand CmdDelete { get; private set; }
void setupCommands()
{
CmdSave = new RelayCommand(() =>
{
workProvider.SaveChanges(() =>
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
System.Windows.MessageBox.Show("Saved");
});
});
});
CmdUndo = new RelayCommand(() =>
{
workProvider.UndoChanges();
Resources.View.Refresh();
});
CmdAdd = new RelayCommand(() =>
{
Resource newResource = new Resource()
{
ResourceID = Guid.NewGuid(),
Rate = 125,
Title = "Staff",
UserName = "jsmith"
};
workProvider.AddResource(newResource);
});
CmdDelete = new RelayCommand(() =>
{
workProvider.DelResource(_SelectedResource);
});
}
}
번째 방법은 확실히 바이 2 회 (서버에서 1 시간 및 상기 제 시간을 CollectionViewSource의 구성에있어서의 필터의 이벤트 핸들러를 추가 요구하고, 필터링 데이터로 간주 될 수 있지만 CollectionViewSource)를 사용하면 다음과 같은 이점이 있습니다. 단일 컬렉션이있어 컬렉션 알림을 더 간단하고 쉽게 관리 할 수 있습니다. 컬렉션은 서버에 제출 될 실제 컬렉션입니다. 추가/삭제를 간단하게 관리 할 수 있습니다. 올바른 컬렉션에서 엔티티를 추가/제거하지 않아서 제출할 때 추가/삭제 기능을 시작할 수 없기 때문입니다.
마지막으로 확인해야 할 사항은 다음과 같습니다. collectionviewsource에서 뷰에 영향을주는 여러 변경을 수행 할 때 DeferRefresh()를 사용해야한다는 것을 알고 있습니다.이렇게하면 내부 변경으로 인해 정렬, 그룹화 등의 새로 고침이 발생할 수있는 불필요한 새로 고침을 방지 할 수 있습니다. UI에서 일부 업데이트 변경 사항을 처리 할 때 .View.Refresh()를 호출하는 것도 중요합니다. .View.Refresh()는 예기치 않은 UI 업데이트를 방지하는 대신 UI 업데이트를 실제로 발생시키기 때문에 DeferRefresh()보다주의하는 것이 더 중요합니다.
다른 사람들에게 도움이 될지 모르겠지만 그렇게되기를 바랍니다. 나는 이것들을 통해 일하고 이것을 이해하려고 노력하는 데 시간을 보낸다. 추가 할 사항이나 기타 사항이 있으시면 언제든지 알려 주시기 바랍니다.