Итак, я предполагаю, что вы пытаетесь вызвать событие от выбранного вами бренда, чтобы сообщить кому-либо, что рейтинг бренда равен (), который затем используется для расчета итогового значения.
Шаг 1:
Вам нужно добавить событие в свой класс «Бренд» и создать открытый метод для его внутреннего вызова.
class Brand
{
public string Name { get; set; }
public Rate Rate { get; set; }
public void SelectBrand() => OnBrandSelect?.Invoke(this, Rate);
public event EventHandler<Rate> OnBrandSelect;
}
Шаг 2:
Подключайте события своего бренда, когда вы загружаете их в коллекцию, которая содержит их, которые используются в качестве источника сетки. Базовый пример ниже.
// 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);
}
Шаг 3:
Затем, когда вы выбираете свой бренд из сетки, вы вызываете событие бренда. Любые слушатели должны затем выполнять свою работу.
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();
}
}
ПРИМЕЧАНИЕ:
Другая сетка, которую я буду называть «Сетка результатов», скорее всего, должна будет отражать эти расчеты на основе скорости, вызванной событием, в столбце Общая сумма.
Я предполагаю, что эти элементы в вашей "таблице результатов" являются фактическими объектами результата,
но я не вижу четкой связи между записью результата и
выбранный бренд. (если только он не спрятан в объекте результата). Который
заставляет меня поверить, что вы просто добавляете запись в таблицу результатов при выборе бренда и забываете ее.
Вам нужно будет встроить ту же ссылку на объект Brand, которую вы загрузили в свою таблицу Brands Grid, в свой объект результата и перехватить его событие внутри объекта результата. (Почти так же, как на втором шаге). Тогда вы можете проигнорировать второй шаг и использовать ниже.
Пример:
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 в конструкции невозможно, поскольку вам необходимо заранее создать экземпляр объекта результата.
Выполните следующие действия:
1) Создайте объект бренда, как он есть на первом этапе. Просто замените тариф на двойной.
2) Добавьте метод "Calculate (double rate)" к вашему результирующему объекту, который принимает double. В рамках этого метода вы запускаете вычисления для итогов и задаете свойство итогов.
public void Caculate(double rate)
{
TotalAmount = TotalArea * rate;
}
3) Итак, теперь вам нужен какой-то способ, чтобы держать ваше событие подписанным на выбранную строку сетки в таблице результатов. Поэтому каждый раз, когда вы добавляете объект результата в свою исходную коллекцию сетки, вам нужно будет привязывать к нему каждое событие объекта бренда.
Так что я предполагаю, что где-то у вас есть кнопка, которая добавляет новую запись в таблицу результатов, которая будет настроена пользователем, а затем он выбирает марку. Непосредственно перед точкой, где вы добавляете объект в результирующий объект. Крюк со следующим.
ResultObject resultObj = new ResultObject()
BrandCollection.All(brand =>
{
brand.OnBrandSelect += (s, rate) =>
{
resultObj.Calculate(rate);
}; return true;
});
resultGridCollection.Add(resultObj);
Так что теперь у каждого объекта бренда есть подключаемая функция, которая вычисляет и устанавливает существующий объект результата при выборе. Вы по-прежнему используете Шаг 3, чтобы вызвать событие выбора.
Имейте в виду, что вам нужно будет отписываться от всех событий бренда каждый раз, когда вы добавляете новый объект, иначе выбор бренда будет продолжать изменять все ваши результаты. Если вы хотите поддержать изменения для выбранного GridResult, вам просто нужно переместить код подписки из метода add в метод выбранной ячейки сетки для результата.
Надеюсь, все это имеет смысл.
Обновление 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
}
}
Просто чтобы заметить, я заметил, что выбор по сетке не очень надежен. Вам просто нужно разобраться в этом. Кажется, когда сетка получает фокус и впервые выбрана, это не вызывает SelectedCellsChanged.
UPDATE
Вот код, основанный на размещенном вами обновлении.
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;
}
}