Пишу сейчас тестовый проект на Wpf C# с использованием MVVM. До этого работал с WinForm, поэтому для меня отсутствие обработчиков событий в новинку. Программа должна считать значение функции, типов которой имеется 5 штук. Есть две модели: Variables:
public class Variables : NotifyPropertyChanged
{
private int _x;
private int _y;
private double _f;
public Variables()
{
X = 0;
Y = 0;
_f = 0;
}
public int X
{
get => _x;
set
{
_x = value;
OnPropertyChanged("F");
}
}
public string XChecker
{
get => X.ToString();
set
{
int index = value.Length - 1;
if (index == -1)
{
X = 0;
}
else if (value[index] >= 48 && value[index] <= 57 && index >= 0)
{
X = int.Parse(value);
}
OnPropertyChanged("VariablesSetsList");
}
}
public int Y
{
get => _y;
set
{
_y = value;
OnPropertyChanged("F");
}
}
public string YChecker
{
get => Y.ToString();
set
{
int index = value.Length - 1;
if (index == -1)
{
Y = 0;
}
else if (value[index] >= 48 && value[index] <= 57 && index >= 0)
{
Y = int.Parse(value);
}
OnPropertyChanged("CurrentVariablesSet");
}
}
public double F
{
get => _f;
set
{
_f = value;
OnPropertyChanged("F");
}
}
public void SetF(int a, int b, int c, string funcType)
{
int n = 0;
switch (funcType)
{
case "Линейная":
n = 1;
break;
case "Квадратичная":
n = 2;
break;
case "Кубическая":
n = 3;
break;
case "4-ой степени":
n = 4;
break;
case "5-ой степени":
n = 5;
break;
default:
break;
}
_f = (a * Math.Pow(X, n)) + (b * Math.Pow(Y, n - 1)) + c;
OnPropertyChanged("F");
}
}
И FuncModel:
public class FuncTemplate : NotifyPropertyChanged
{
private string _funcType;
private int _a;
private int _b;
private List<int> _c;
private int _currentC;
private ObservableCollection<Variables> _variablesSetsList;
private Variables _currentVariablesSet;
public FuncTemplate(string funcType)
{
_funcType = funcType;
C = new List<int>();
_variablesSetsList = new ObservableCollection<Variables>();
_currentVariablesSet = new Variables();
}
public string FuncType
{
get => _funcType;
set
{
_funcType = value;
OnPropertyChanged("FuncType");
}
}
public int A
{
get => _a;
set
{
_a = value;
OnPropertyChanged("A");
}
}
public string AChecker
{
get => A.ToString();
set
{
int index = value.Length - 1;
if (index == -1)
{
A = 0;
}
else if (value[index] >= 48 && value[index] <= 57 && index >= 0)
{
A = int.Parse(value);
}
OnPropertyChanged("A");
}
}
public int B
{
get => _b;
set
{
_b = value;
OnPropertyChanged("B");
}
}
public string BChecker
{
get => B.ToString();
set
{
int index = value.Length - 1;
if (index == -1)
{
B = 0;
}
else if (value[index] >= 48 && value[index] <= 57 && index >= 0)
{
B = int.Parse(value);
}
OnPropertyChanged("B");
}
}
public List<int> C
{
get => _c;
set
{
switch (FuncType)
{
case "Линейная":
_c = new List<int> { 1, 2, 3, 4, 5 };
break;
case "Квадратичная":
_c = new List<int> { 10, 20, 30, 40, 50 };
break;
case "Кубическая":
_c = new List<int> { 100, 200, 300, 400, 500 };
break;
case "4-ой степени":
_c = new List<int> { 1000, 2000, 3000, 4000, 5000 };
break;
case "5-ой степени":
_c = new List<int> { 10000, 20000, 30000, 40000, 50000 };
break;
default:
break;
}
OnPropertyChanged("C");
}
}
public int CurrentC
{
get => _currentC;
set
{
_currentC = value;
OnPropertyChanged("CurrentC");
}
}
/// <summary>
/// Свойство поля _variablesSetsList, являющегося коллекцией наборов
/// значений переменных x, y, f. При установке значения оповещает
/// систему об изменении свойства.
/// </summary>
public ObservableCollection<Variables> VariablesSetsList
{
get => _variablesSetsList;
set
{
_variablesSetsList = value;
OnPropertyChanged("VariablesSetsList");
}
}
/// <summary>
/// Свойство поля _currentVariablesSet, содержащего выбранный набор переменных.
/// В сеттере проверяет, существует ли набор, и либо создает его,
/// либо устанавливает значения в существующий, после чего оповещает
/// систему об изменении свойства.
/// </summary>
public Variables CurrentVariablesSet
{
get => _currentVariablesSet;
set
{
if (value == null)
_currentVariablesSet = new Variables();
else
{
_currentVariablesSet = value;
_currentVariablesSet.SetF(A, B, CurrentC, FuncType);
}
OnPropertyChanged("CurrentVariablesSet");
}
}
}
Вторая - шаблон функции, а первая содержит свой набор переменных для каждой функции.
Также есть View:
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="190"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel
Name="FuncTypesListStackPanel"
Grid.Row="0"
Grid.Column="0">
<Label
Content="Тип функции:"
Name="FuncTypeLabel"
Grid.Row="0"
Grid.Column="0"
FontWeight="Bold"
FontSize="12"
HorizontalAlignment="Center"
Margin="10,0,10,0"
VerticalAlignment="Top"/>
<ListBox
Name="FunctionTypesListBox"
VerticalAlignment="Bottom"
Margin ="10,0,10,10"
ItemsSource="{Binding Functions}"
SelectedItem="{Binding CurrentFunction}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="12" Text="{Binding Path=FuncType}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel
Name="CurrentFuncFactorsStackPanel"
Grid.Row="0"
Grid.Column="1"
DataContext="{Binding CurrentFunction}">
<Label
Content="A:"
Name="FactorALabel"
FontSize="12"
FontWeight="Bold"
HorizontalAlignment="Left"
Margin="10,0,0,0"/>
<TextBox
Name="FactorATexBox"
HorizontalAlignment="Stretch"
Margin="10,0,150,0"
VerticalContentAlignment="Top"
FontSize="12"
Text="{Binding AChecker, UpdateSourceTrigger=PropertyChanged}"/>
<Label
Content="B:"
Name="FactorBLabel"
FontSize="12"
FontWeight="Bold"
HorizontalAlignment="Left"
Margin="10,0,0,0"/>
<TextBox
Name="FactorBTexBox"
HorizontalAlignment="Stretch"
Margin="10,2,150,2"
VerticalContentAlignment="Center"
FontSize="12"
Text="{Binding BChecker, UpdateSourceTrigger=PropertyChanged}"/>
<Label
Content="C"
Name="FactorCLabel"
FontSize="12"
FontWeight="Bold"
HorizontalAlignment="Left"
Margin="10,0,0,0"/>
<ComboBox
Name="FactorCComboBox"
HorizontalAlignment="Stretch"
Margin="10,2,150,2"
FontSize="12"
VerticalContentAlignment="Top"
ItemsSource="{Binding C}"
SelectedItem="{Binding CurrentC}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="12" Text="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<ScrollViewer
Name="TableScrollViewer"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
DataContext="{Binding CurrentFunction}"
>
<DataGrid
Name="TableDataGrid"
ColumnHeaderHeight="25"
CanUserAddRows="True"
ItemsSource="{Binding VariablesSetsList}"
SelectedItem ="{Binding CurrentVariablesSet}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="x"
Binding="{Binding XChecker, UpdateSourceTrigger=PropertyChanged}"
Width="*"/>
<DataGridTextColumn Header="y"
Binding="{Binding YChecker, UpdateSourceTrigger=PropertyChanged}"
Width="*"/>
<DataGridTextColumn Header="f(x,y)"
IsReadOnly = "True"
Binding="{Binding F}"
Width="*">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</Grid>
Т.е. последний DataGrid представляет собой таблицу значений для X, Y, F. F должна высчитываться автоматически, сам столбец доступен только на чтение. И я не могу понять, как его таким сделать? Пробовал функцию подсчёта прописать в сеттер выбранного набора переменных, но тогда значение F меняется только при перещелкивании с на другую строку таблицы и обратно. в сеттер F прописать её не могу, так как оттуда нет доступа к коэффициентом A,B,C и типу функции. Подскажите, что можно с этим сделать? Может, я как-то неправильно использую Binding? Уже две недели не могу решить эту проблему.
Variables, для начала вы его назвали "Переменные", то есть это некий список различных переменных. Далее смотрим наXи наY, видим, что они идентичны, как в плане "чекера", так и в плане переменной. Аналогично кстати и у классаFuncTemplate. Все это сводится к тому, что вам надо сделать класс, который будет отвечать за одну переменную, и заполнить далее простую коллекцию ими, ну а дальше, можно сделать уже такое. – EvgeniyZ Aug 30 '23 at 17:15