2016-11-14 158 views
0

我想将数据绑定到某种自定义依赖项属性或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是一个数据库中的参考。我这样做是为了计算每行最后一列的小计。现在,我用DataGridTemplateColumnTextBox里面,所以我可以Tag它与tkey 我也阅读了有关这些事情的TechNet,但似乎没有指出我到底想做什么。我甚至不确定这是可能的,但看起来会是这样。

编辑:

这是我使用的尝试拨打标签上CellEditEnding发射约手头的问题

private void resultsDg_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) 
    { 
     MessageBox.Show(TagTextColumns.GetTag(sender as DataGridTextColumn).ToString()); 
    } 

更多细节代码:我想从四个方面 数据库在用户进行更改时动态计算最后一列的小计。我试图使用Linq到SQL,但使用System.Data.SqlClientSystem.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; 
    } 
+0

究竟是什么问题? – redcurry

+0

告诉我们你想达到什么。看起来你只是想有一个额外的小计专栏。 http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – Mat

+0

在RegisterAttached方法改变'typeof(DataGridColumn)'为'typeof(TagTextColumns)'。也无需从[DependencyObject]派生[附加属性](http://stackoverflow.com/a/11535994/4838058)。 – Funk

回答

0

您可以使用MVVM模式来计算ViewModel中的小计。这是一个应该引导你走向正确方向的例子。在MainView的构造函数中,我创建了2个课程并应用学生。一门课程的财产TotalWeight计算所有学生的总重量。如果学生的体重发生变化,或者学生被添加/移除到课程中,我们必须更新UI上的值。这由于INotifyPropertyChangedObservableCollection

如果您使用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 
}