因此,我假设您正试图调用所选品牌中的一个事件来向列出的任何人传达品牌率为(),然后用它来计算总数。
第一步:
您需要向“Brand”类添加一个事件,并创建一个公共方法在内部调用它。
class Brand
{
public string Name { get; set; }
public Rate Rate { get; set; }
public void SelectBrand() => OnBrandSelect?.Invoke(this, Rate);
public event EventHandler<Rate> OnBrandSelect;
}
第二步:
当您将品牌事件加载到包含它们的集合(用作网格源)时,将它们挂接起来。基本示例如下。
// load brands from db or elswhere.
List<Brand> brandsSelectedToLoad = new List<Brand>()
ObservableCollection<Brand> BrandDisplayCollectionToBeUsedAsGridSource = new ObservableCollection<Brand>();
foreach (Brand brand in brandsSelectedToLoad)
{
brand.OnBrandSelect += (s, args) => { /* Call calculation method (TotalAmount = TotalArea * args -- args is rate) and set the result */}
BrandDisplayCollectionToBeUsedAsGridSource.Add(brand);
}
第三步:
private void BrandGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
List<DataGridCellInfo> info = BrandGrid.SelectedCells.ToList();
if (info.Count > 0)
{
Brand selectedBrand = info[1].Item as Brand;
if (selectedBrand == null)
return;
selectedBrand.SelectBrand();
}
}
注:
我将称之为“结果网格”的另一个网格很可能需要在totalamount列中根据事件调用的速率反映这些计算。
但我看不出结果记录和
精选品牌(除非它隐藏在结果对象中)。哪个
让我相信你只是将记录添加到brand select的结果网格中,然后忘记它。
您需要将加载到Brands网格中的同一Brand对象引用嵌入到结果对象中,并将其事件挂接到结果对象中(几乎与第二步相同)。你可以忽略第二步,然后使用下面的。
例子:
class Result : INotifyPropertyChanged
{
private double total;
public Result(Brand brandRef)
{
this.Brand = brandRef;
brand.OnBrandSelect += (s, args) =>
{
/* Call calculation method (TotalAmount = TotalArea *
args -- args is rate) and set the result */
Total = /*(TotalAmount = TotalArea *
args -- args is rate)*/;
}
}
public double Total
{
get { return total; }
set
{
total = value;
NotifyPropertyChanged();
}
}
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
更新响应
我懂了。因此,只有在用户配置了长度和数量输入之后,品牌选择才可用。因此,在构造中使用brand参数是不可能的,因为您需要预先实例化result对象。
执行以下操作:
1) 创建品牌对象,因为我在第一步。就用双倍的价格代替吧。
public void Caculate(double rate)
{
TotalAmount = TotalArea * rate;
}
所以我假设在某个地方有一个按钮,它将一个新记录添加到结果网格中,由用户配置,然后他选择品牌。就在将对象添加到结果对象集合的点之前。用下面的钩子钩住它。
ResultObject resultObj = new ResultObject()
BrandCollection.All(brand =>
{
brand.OnBrandSelect += (s, rate) =>
{
resultObj.Calculate(rate);
}; return true;
});
resultGridCollection.Add(resultObj);
所以现在每个brand对象都有一个钩子函数,用于计算和设置select上的现有结果对象。您仍然使用步骤3来调用选择事件。
请记住,每次添加新对象时,您都需要取消订阅所有品牌活动,否则品牌选择将不断更改您的所有结果。如果您想支持对选定的GridResult进行更改,只需将订阅代码从add方法移动到result的选定网格单元方法。
更新2
namespace GridSelection
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MainWindowViewModel model = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
OrdersGrid.SelectedCellsChanged += OrdersGrid_SelectedCellsChanged;
BrandGrid.SelectedCellsChanged += BrandGrid_SelectedCellsChanged;
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
model.Load();
this.DataContext = model;
}
private void OrdersGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
DataGrid grid = sender as DataGrid;
Order selectedOrder = grid.SelectedItem as Order;
if (selectedOrder == null)
return;
model.BrandCollection.All(b =>
{
b.UnsubscribeAll();
b.OnBrandSelect += (s, rate) =>
{
selectedOrder.CalculateTotal(rate);
}; return true;
});
}
private void BrandGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
DataGrid grid = sender as DataGrid;
Brand selectedbrand = grid.SelectedItem as Brand;
if (selectedbrand == null)
return;
selectedbrand.InvokeBrandSelected();
}
}
internal class MainWindowViewModel
{
public ObservableCollection<Brand> BrandCollection { get; private set; }
public ObservableCollection<Order> OrderCollection { get; private set; }
public ICommand AddNewOrderCommand { get; private set; }
public void Load()
{
BrandCollection = new ObservableCollection<Brand>
{
new Brand() { Name = "Brand One", Rate = 20 },
new Brand() { Name = "Brand Two", Rate = 30 },
new Brand() { Name = "Brand Three", Rate = 50 }
};
OrderCollection = new ObservableCollection<Order>();
AddNewOrderCommand = new CustomCommand(p =>
{
OrderCollection.Add(new Order());
});
}
}
public class Order : INotifyPropertyChanged
{
#region Private Variables
private int length;
private int quantity;
private int totalArea;
private double totalAmount;
#endregion
#region Public Properties
public int Length
{
get { return length; }
set
{
length = value;
NotifyPropertyChanged();
CalculateArea();
}
}
public int Quantity
{
get { return quantity; }
set
{
quantity = value;
NotifyPropertyChanged();
CalculateArea();
}
}
public int TotalArea
{
get { return totalArea; }
set
{
totalArea = value;
NotifyPropertyChanged();
}
}
public double TotalAmount
{
get { return totalAmount; }
set
{
totalAmount = value;
NotifyPropertyChanged();
}
}
#endregion
private void CalculateArea()
{
TotalArea = this.Length * this.Quantity;
}
public void CalculateTotal(double rate)
{
TotalAmount = this.TotalArea * rate;
}
#region Public Methods
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public class Brand
{
public string Name { get; set; }
public double Rate { get; set; }
public void InvokeBrandSelected() => OnBrandSelect?.Invoke(this, Rate);
public void UnsubscribeAll() => OnBrandSelect = null;
public event EventHandler<double> OnBrandSelect;
}
// Interface
public interface ICustomCommand : ICommand
{
event EventHandler<object> Executed;
}
// Command Class
public class CustomCommand : ICustomCommand
{
#region Private Fields
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
#endregion
#region Constructor
public CustomCommand(Action<object> execute) : this(execute, null)
{
}
public CustomCommand(Action<object> execute, Func<object, bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute ?? (x => true);
}
#endregion
#region Public Methods
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter = null)
{
Refresh();
_execute(parameter);
Executed?.Invoke(this, parameter);
Refresh();
}
public void Refresh()
{
CommandManager.InvalidateRequerySuggested();
}
#endregion
#region Events
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public event EventHandler<object> Executed;
#endregion
}
}
我注意到,ongrid select不是很可靠。你只需要研究一下,当网格获得焦点并第一次被选中时,似乎不会触发被选中的单元格。
以下是基于您发布的更新的代码。
namespace GridSelection
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MainWindowViewModel model = new MainWindowViewModel();
public MainWindow()
{
InitializeComponent();
BrandGrid.MouseDoubleClick += BrandGrid_MouseDown;
OrdersGrid.InitializingNewItem += OrdersGrid_InitializingNewItem; ;
this.Loaded += MainWindow_Loaded;
}
private void OrdersGrid_InitializingNewItem(object sender, InitializingNewItemEventArgs e)
{
Order newOrder = e.NewItem as Order;
if (newOrder == null)
return;
if(model.CurrentBrand != null)
{
newOrder.UpdateRate(model.CurrentBrand.Rate);
}
model.BrandCollection.All(b =>
{
b.OnBrandSelect += (s, rate) =>
{
newOrder.UpdateRate(model.CurrentBrand.Rate);
newOrder.CalculateTotal();
}; return true;
});
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
model.Load();
this.DataContext = model;
}
private void BrandGrid_MouseDown(object sender, MouseButtonEventArgs e)
{
DataGrid grid = sender as DataGrid;
Brand selectedbrand = grid.SelectedItem as Brand;
if (selectedbrand == null)
return;
selectedbrand.InvokeBrandSelected();
}
}
internal class MainWindowViewModel : INotifyPropertyChanged
{
private Brand currentBrand;
public ObservableCollection<Brand> BrandCollection { get; private set; }
public ObservableCollection<Order> OrderCollection { get; private set; }
public Brand CurrentBrand
{
get { return currentBrand; }
set
{
currentBrand = value;
NotifyPropertyChanged();
}
}
public void Load()
{
BrandCollection = new ObservableCollection<Brand>
{
new Brand() { Name = "Brand One", Rate = 20 },
new Brand() { Name = "Brand Two", Rate = 30 },
new Brand() { Name = "Brand Three", Rate = 50 }
};
OrderCollection = new ObservableCollection<Order>();
}
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Order : INotifyPropertyChanged
{
#region Private Variables
private int length;
private int quantity;
private int totalArea;
private double totalAmount;
#endregion
public Order()
{
}
#region Properties
private double Rate { get; private set; }
public int Length
{
get { return length; }
set
{
length = value;
NotifyPropertyChanged();
CalculateArea();
CalculateTotal();
}
}
public int Quantity
{
get { return quantity; }
set
{
quantity = value;
NotifyPropertyChanged();
CalculateArea();
CalculateTotal();
}
}
public int TotalArea
{
get { return totalArea; }
set
{
totalArea = value;
NotifyPropertyChanged();
}
}
public double TotalAmount
{
get { return totalAmount; }
set
{
totalAmount = value;
NotifyPropertyChanged();
}
}
#endregion
#region Methods
private void CalculateArea()
{
TotalArea = this.Length * this.Quantity;
}
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void CalculateTotal()
{
TotalAmount = this.TotalArea * this.Rate;
}
public void UpdateRate(double rate)
{
Rate = rate;
}
#endregion
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public class Brand
{
public string Name { get; set; }
public double Rate { get; set; }
public void InvokeBrandSelected() => OnBrandSelect?.Invoke(this, Rate);
public void UnsubscribeAll() => OnBrandSelect = null;
public event EventHandler<double> OnBrandSelect;
}
}