C#WPF DataGridTextColumn自定义属性
我想将数据绑定到某种自定义依赖项属性或WPF中的附加属性。我已经使用了以下问题 和答案-How to create Custom Property for WPF DataGridTextColumn 作为参考框架,但我需要绑定到WPF中的“标记”。我们可以称之为任何,但是我将它称为简单标签,因为我在代码的其他部分使用了复选框和文本框。我的班级如下:C#WPF DataGridTextColumn自定义属性
public class TagTextColumns : DependencyObject
{
public static readonly DependencyProperty TagProperty = DependencyProperty.RegisterAttached(
"Tag",
typeof(object),
typeof(DataGridColumn),
new FrameworkPropertyMetadata(null));
public static object GetTag(DependencyObject dependencyObject)
{
return dependencyObject.GetValue(TagProperty);
}
public static void SetTag(DependencyObject dependencyObject, object value)
{
dependencyObject.SetValue(TagProperty, value);
}
}
我想设置我在WPF DataGridTextColumn类似于下面的内容:
<DataGridTextColumn Binding="{Binding Customer}" Header="Customer" local:TagTextColumns.Tag="{Binding tkey}"/>
其中TKEY是一个数据库中的参考。我这样做是为了计算每行最后一列的小计。现在,我用DataGridTemplateColumn
与TextBox
里面,所以我可以Tag
它与tkey 我也阅读了有关这些事情的TechNet,但似乎没有指出我到底想做什么。我甚至不确定这是可能的,但看起来会是这样。
编辑:
这是我使用的尝试拨打标签上CellEditEnding
发射约手头的问题
private void resultsDg_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
MessageBox.Show(TagTextColumns.GetTag(sender as DataGridTextColumn).ToString());
}
更多细节代码:我想从四个方面 数据库在用户进行更改时动态计算最后一列的小计。我试图使用Linq到SQL,但使用System.Data.SqlClient
和System.Data
要快得多。也许有人可以给我一个更好的方法。计算代码如下:
private void CalculateAscessorials(string tkey)
{
decimal SplitTerm = Properties.Settings.Default.SplitTerminal;
decimal SplitDrop = Properties.Settings.Default.SplitDrop;
decimal SiteSplit = Properties.Settings.Default.OnSiteSplit;
decimal Trainer = Properties.Settings.Default.TrainerLoad;
decimal WaitTime = Properties.Settings.Default.TerminalWait;
decimal PumpOut = Properties.Settings.Default.PumpOut;
DataRow[] row = resultDetail.Select("tkey = " + tkey);
decimal payRate;
decimal tempLineItem;
Decimal.TryParse(row[0]["PayForLine"].ToString(), out tempLineItem);
Decimal.TryParse(row[0]["PayRate"].ToString(), out payRate);
if (payRate == 0 && tempLineItem > 0) //this change affts if the rate is 0, that is no rate defined, the rate entered becomes the pay rate for that line only for calculations
row[0]["PayRate"] = tempLineItem;
if (!Convert.ToBoolean(row[0]["SplitDrop"]))
{
Decimal.TryParse(row[0]["PayRate"].ToString(), out payRate);
}
else if (Convert.ToBoolean(row[0]["SplitDrop"]))
{
payRate = SplitDrop;
}
//decimal linePay;
// Decimal.TryParse(row[0]["PayForLine"].ToString(), out linePay);
int terms;
Int32.TryParse(row[0]["SplitLoad"].ToString(), out terms);
decimal waits;
Decimal.TryParse(row[0]["WaitTime"].ToString(), out waits);
int pumps;
Int32.TryParse(row[0]["PumpOut"].ToString(), out pumps);
int sites;
Int32.TryParse(row[0]["SiteSplit"].ToString(), out sites);
int trainings;
Int32.TryParse(row[0]["Trainer"].ToString(), out trainings);
row[0]["PayForLine"] =
(SplitTerm * terms)
+ (waits * WaitTime)
+ (pumps * PumpOut)
+ (sites * SiteSplit)
+ (trainings * Trainer)
+ payRate;
}
您可以使用MVVM模式来计算ViewModel中的小计。这是一个应该引导你走向正确方向的例子。在MainView的构造函数中,我创建了2个课程并应用学生。一门课程的财产TotalWeight
计算所有学生的总重量。如果学生的体重发生变化,或者学生被添加/移除到课程中,我们必须更新UI上的值。这由于INotifyPropertyChanged
和ObservableCollection
。
如果您使用LinqToSQL或更好的EntityFramework,您可以从商店获得。你可以将它注入ViewModel构造函数中作为acutal模型。也许你甚至想为此介绍一个MainViewModel。为了简单起见,我跳过了这个。但你可能想看看dependency injection。
XAML:
<DataGrid ItemsSource="{Binding}">
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Students}"></DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
后面的代码:
public class CourseViewModel : ViewModelBase
{
#region Fields
private string _name;
private ObservableCollection<StudentViewModel> _students;
#endregion Fields
#region Constructors
public CourseViewModel()
{
_students = new ObservableCollection<StudentViewModel>();
_students.CollectionChanged += _students_CollectionChanged;
}
#endregion Constructors
#region Properties
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
public ObservableCollection<StudentViewModel> Students
{
get
{
return _students;
}
}
public double TotalWeight
{
get
{
return Students.Sum(x => x.Weight);
}
}
#endregion Properties
#region Methods
private void _students_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
// add/remove property changed handlers to students
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (StudentViewModel student in e.NewItems)
{
student.PropertyChanged += Student_PropertyChanged;
}
}
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (StudentViewModel student in e.OldItems)
{
student.PropertyChanged -= Student_PropertyChanged;
}
}
//students were added or removed to the course -> inform "listeners" that TotalWeight has changed
OnPropertyChanged(nameof(TotalWeight));
}
private void Student_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//the weight of a student has changed -> inform "listeners" that TotalWeight has changed
if (e.PropertyName == nameof(StudentViewModel.Weight))
{
OnPropertyChanged(nameof(TotalWeight));
}
}
#endregion Methods
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region Constructors
public MainWindow()
{
InitializeComponent();
var course1 = new CourseViewModel() { Name = "Course1" };
course1.Students.Add(new StudentViewModel() { Weight = 100, Name = "Mark" });
course1.Students.Add(new StudentViewModel() { Weight = 120, Name = "Olaf" });
course1.Students.Add(new StudentViewModel() { Weight = 111, Name = "Hans" });
var course2 = new CourseViewModel() { Name = "Course2" };
course2.Students.Add(new StudentViewModel() { Weight = 100, Name = "Mark" });
course2.Students.Add(new StudentViewModel() { Weight = 90, Name = "Renate" });
course2.Students.Add(new StudentViewModel() { Weight = 78, Name = "Judy" });
DataContext = new List<CourseViewModel>()
{
course1,
course2
};
}
#endregion Constructors
}
public class StudentViewModel : ViewModelBase
{
#region Fields
private string _name;
private double _weight;
#endregion Fields
#region Properties
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
public double Weight
{
get
{
return _weight;
}
set
{
_weight = value;
OnPropertyChanged();
}
}
#endregion Properties
}
究竟是什么问题? – redcurry
告诉我们你想达到什么。看起来你只是想有一个额外的小计专栏。 http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Mat
在RegisterAttached方法改变'typeof(DataGridColumn)'为'typeof(TagTextColumns)'。也无需从[DependencyObject]派生[附加属性](http://stackoverflow.com/a/11535994/4838058)。 – Funk