这是我在这里的第一篇文章,我一直在尝试在其他问题中找到的一些技巧,但似乎无法让我的工作像我想要的那样...... 我正在更改现有的应用程序(.net 3.5使用WPF和C#,实体框架使用sqlserver2008)。我是EFDM和WPF的新手。 新版本需要与以前版本的现有数据库完全兼容,而不对现有数据库进行任何修改,因此我非常不愿意更改数据模型及其生成的任何对象。
无论如何,这是我的问题: 我有来自edm的对象“staffincentive”和“staffincentivelines”,每个员工都有0到多个staffincentiveline附加。 我将它们显示为树视图,并且需要能够动态添加或删除staffincentiveline。
<TreeView ItemsSource="{Binding}" Name="MainTree">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding staffincentiveline}">
<TextBox Text="{Binding name}"/>
<Button Tag="{Binding}" Click="addline" Content="Add Line" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate >
<TextBox Text="{Binding lbound}"/>
<TextBox Text="{Binding percentage}"/>
<Button Tag="{Binding}" Click="delLine" Content="Remove"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
这样可以正常工作,但是staffincentiveline没有排序,但它们确实需要按顺序出现(升序lbound)。 所以我找了一个解决方案并找到了一个转换器
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{return
((EntityCollection<staffincentiveline>)value).OrderBy(o => o.lbound);}
然后我意识到现在当我使用屏幕上的按钮添加或删除staffincentiveline时,不会显示更改。如果我理解是因为激励线是通过Sort Converter提供的视图显示的,并且在对集合进行更改时不会刷新视图。如果我再次理解正确,这是因为EntityCollection没有实现INotifyPropertyChanged。
如果我使用
刷新视图
CollectionViewSource.GetDefaultView(_incentives).REFRESH();然后所有的树视图都会刷新,所有项目都会被折叠,这对用户来说非常困惑......
那么如何在不改变我的对象类staffincentive和staffincentiveline的情况下进行排序和刷新工作呢?我应该创建另一个包含它们的类并实现INotifyPropertyChanged吗?
由于
答案 0 :(得分:0)
我设法做到了:)
我创建了2个类StaffIncentiveHelperObject和StaffIncentiveLineHelperObject,它们实现了INotifyPropertyChanged。当通过访问者进行更改时,它们会重叠现有类和触发事件。 您可以使用从StaffIncentiveHelperObject中的ObservableCollection添加/删除StaffIncentiveLineHelperObject的方法,这些方法还可以从EDM中添加/删除原始对象...这是有效地将对视图所做的更改与数据库链接的位。
public class StaffIncentiveHelperObject : INotifyPropertyChanged//
{
public delegate void CollectionChangedDelegate();
public static CollectionChangedDelegate CollectionChanged;
public StaffIncentiveHelperObject(staffincentive input)
{
this._StaffIncentive = input;
}
private staffincentive _StaffIncentive;
public staffincentive StaffIncentive
{
get { return _StaffIncentive; }
set
{
if (_StaffIncentive == value) return;
_StaffIncentive = value;
OnPropertyChanged("StaffIncentive");
}
}
public decimal? StaffIncentiveIncrement
{
get
{
return _StaffIncentive.increment;
}
set
{
if (_StaffIncentive.increment != value)
{
_StaffIncentive.increment = value;
OnPropertyChanged("StaffIncentive");
}
}
}
public string StaffIncentiveName
{
get
{
return _StaffIncentive.name;
}
set
{
if (_StaffIncentive.name != value)
{
_StaffIncentive.name = value;
OnPropertyChanged("StaffIncentive");
}
}
}
public byte? StaffIncentiveType
{
get
{
return _StaffIncentive.type;
}
set
{
if(_StaffIncentive.type != value)
{
_StaffIncentive.type = value;
OnPropertyChanged("StaffIncentive");
}
}
}
private ObservableCollection<StaffIncentiveLineHelperObject> _StaffIncentiveLines = new ObservableCollection<StaffIncentiveLineHelperObject>();
public ObservableCollection<StaffIncentiveLineHelperObject> StaffIncentiveLines
{
get { return _StaffIncentiveLines; }
set { _StaffIncentiveLines = value; OnPropertyChanged("StaffIncentiveLines"); }
}
public void AddStaffIncentiveLine( staffincentiveline SIL)
{
SIL.staffincentive = this._StaffIncentive;
_StaffIncentive.staffincentiveline.Add(SIL);
StaffIncentiveLines.Add(new StaffIncentiveLineHelperObject(SIL, this));
//OnPropertyChanged("StaffIncentiveLine");
if (CollectionChanged != null)
{
CollectionChanged.Invoke();
}
}
public void RemoveStaffIncentiveLine(StaffIncentiveLineHelperObject SILHO)
{
_StaffIncentive.staffincentiveline.Remove(SILHO.StaffIncentiveLine);
_StaffIncentiveLines.Remove(SILHO);
//OnPropertyChanged("StaffIncentiveLine");
if (CollectionChanged != null)
{
CollectionChanged.Invoke();
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
var x = PropertyChanged;
if (x != null)
x(this, new PropertyChangedEventArgs(name));
}
#endregion
}
public class StaffIncentiveLineHelperObject : INotifyPropertyChanged//, INotifyCo
{
public StaffIncentiveLineHelperObject(staffincentiveline input, StaffIncentiveHelperObject parent)
{
this._StaffIncentiveLine = input;
this.Parent = parent;
}
public StaffIncentiveHelperObject Parent { get; set;}
private staffincentiveline _StaffIncentiveLine;
public staffincentiveline StaffIncentiveLine
{
get { return _StaffIncentiveLine; }
set
{
if (_StaffIncentiveLine == value) return;
_StaffIncentiveLine = value;
OnPropertyChanged("StaffIncentiveLine");
}
}
public decimal? StaffIncentiveLineLbound
{
get
{
return _StaffIncentiveLine.lbound;
}
set
{
if (_StaffIncentiveLine.lbound != value)
{
_StaffIncentiveLine.lbound = value;
OnPropertyChanged("StaffIncentiveLine");
}
}
}
public double? StaffIncentiveLinePercentage
{
get
{
return _StaffIncentiveLine.percentage;
}
set
{
if (_StaffIncentiveLine.percentage != value)
{
_StaffIncentiveLine.percentage = value;
OnPropertyChanged("StaffIncentiveLine");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
var x = PropertyChanged;
if (x != null)
x(this, new PropertyChangedEventArgs(name));
}
#endregion
}
xaml的datacontext设置为ObservableCollection,它只是根据EDM的现有对象构建的,如下所示
ObservableCollection<SupportingObjects.StaffIncentiveHelperObject> myIcentives = new ObservableCollection<SupportingObjects.StaffIncentiveHelperObject>();
foreach (staffincentive SI in db_incentives)
{
StaffIncentiveHelperObject SIHO = new StaffIncentiveHelperObject(SI);
myIcentives.Add(SIHO);
foreach (staffincentiveline SIL in SI.staffincentiveline)
{
SIHO.AddStaffIncentiveLine(SIL);
}
}
然后XAML使用访问者显示/更新它。
<TreeView ItemsSource="{Binding}" Name="MainTree">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding StaffIncentiveLines, Converter={StaticResource IncentiveLineHelperObjectSort}, ConverterParameter=StaffIncentiveLineLbound}">
<StackPanel Orientation="Horizontal" >
<TextBox Text="{Binding StaffIncentiveName}" Width="120" />
<Button Tag="{Binding}" Click="addline" Content="Add Line" />
</StackPanel>
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate >
<StackPanel Orientation="Horizontal" Margin="150,0,0,0">
<TextBox Text="{Binding StaffIncentiveLineLbound, StringFormat='{}{0:c}'}" Width="120" />
<TextBox Text="{Binding StaffIncentiveLinePercentage}" Width="120" />
<Button Tag="{Binding}" Click="delLine" Content="Remove"/>
</StackPanel>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
排序仅在第一次加载时完成,而不是在添加行时动态完成,这对我来说很好。这是排序转换器(我从网站上的另一个问题复制它)
public class IncentiveLineHelperObjectSort : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
System.Collections.ObjectModel.ObservableCollection<StaffIncentiveLineHelperObject> collection = value as System.Collections.ObjectModel.ObservableCollection<StaffIncentiveLineHelperObject>;
ListCollectionView view = new ListCollectionView(collection);
System.ComponentModel.SortDescription sort = new System.ComponentModel.SortDescription(parameter.ToString(), System.ComponentModel.ListSortDirection.Ascending);
view.SortDescriptions.Add(sort);
return view;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
以下是按下按钮时添加或删除staffincentiveline的方法。
private void addline(object sender, RoutedEventArgs e)
{
var incentive = ((sender as Button).Tag as StaffIncentiveHelperObject);
incentive.AddStaffIncentiveLine(new staffincentiveline());
TreeViewItem thisTreeViewItem = MainTree.ItemContainerGenerator.ContainerFromItem(incentive) as TreeViewItem;
thisTreeViewItem.IsExpanded = true;
}
private void delLine(object sender, RoutedEventArgs e)
{
var line = ((sender as Button).Tag as StaffIncentiveLineHelperObject);
StaffIncentiveHelperObject thisIncentive = line.Parent;
thisIncentive.RemoveStaffIncentiveLine(line);
TreeViewItem thisTreeViewItem = MainTree.ItemContainerGenerator.ContainerFromItem(thisIncentive) as TreeViewItem;
if (thisIncentive.StaffIncentiveLines.Count == 0)
{
thisTreeViewItem.IsExpanded = false;
}
}
如果其他人有更好的方法或改进方法,我会很高兴听到它:)