ゼロからはじめるVisual C#日記.5 (データベースとか色々手直しとか)
前の日記
ゼロからはじめるVisual C#日記.4 (SQLite導入とか)
開発が軌道に乗ってきました 多分無敵です。
ある程度できてくるとモチベ永久機関になるから楽しい。逆にここまでが辛い。
データベース設計
前の仮データベースを投げ捨ててしっかり設計します。今回は外部キーは実装では使ってないです。設定方法がよくわからなかった。
Genreはカメラ機材や照明機材など、Machineは具体的な機材名、Equipmentは機材番号。
悩みポイントは、Equipment.IsLending。ある機材が貸出中かどうか知りたいときに、これが無いとIsReturnedがfalseのLendidで貸出中機材一覧を取得するか、LendingEquipmentからその機材のLendIdを取得してIsReturnedを調べていく必要があるので入れたんですけど、こういう一応取得できるものを追加するのはちょっと不安。
考えられるデメリットとしては機材返却時にLendとEquipment両方更新しないとバグる。これやっていいのかな、勉強不足なのでわからない。
まあ専門外なのでゆるして...
(図はこのサイトで作りました。便利だなぁ...)
色々作るよ!
まずFormData.csをデータベースに合わせて作り直し。
public class FormData
{
public string IdDepartment { get; set; }
public string IdYear { get; set; }
public string IdNumber { get; set; }
public string IdName { get; set; }
public string FormClass { get; set; }
public string FormDay { get; set; }
public string FormPeriod { get; set; }
public string FormTeam { get; set; }
public string LendDate { get; set; }
public string ReturnDueDate { get; set; }
public bool IsClass { get; set; }
public bool IsOrg { get; set; }
public List<Equipment> EquipmentList { get; set; }
public class Equipment
{
public string MachineId { get; set; }
public string EquipmentId { get; set; }
public string Remarks { get; set; }
}
}
当たり前ですが、このList<Equipment> EquipmentListは初期化せずに.Add()するとエラーになるので気を付けましょう(1敗)。
SelectTeamも作り直し。団体名も選べるように。SelectTeam.xaml.csでいろいろがんばります。xaml側はスクショから想像できる通りです。
private void ClassBoxChecked(object sender, RoutedEventArgs e)
{
ClassCard.Visibility = System.Windows.Visibility.Visible;
OrgBox.IsEnabled = false;
CheckForm(null, null);
}
private void ClassBoxUnChecked(object sender, RoutedEventArgs e)
{
ClassCard.Visibility = System.Windows.Visibility.Collapsed;
OrgBox.IsEnabled = true;
NextButton.IsEnabled = true;
}
private void OrgBoxChecked(object sender, RoutedEventArgs e)
{
OrgCard.Visibility = System.Windows.Visibility.Visible;
ClassBox.IsEnabled = false;
CheckForm(null, null);
}
private void OrgBoxUnChecked(object sender, RoutedEventArgs e)
{
OrgCard.Visibility = System.Windows.Visibility.Collapsed;
ClassBox.IsEnabled = true;
NextButton.IsEnabled = true;
}
private void CheckForm(object sender, TextChangedEventArgs e)
{
bool res = false;
if ((bool)ClassBox.IsChecked)
{
bool formclass = (TextBoxClass.Text.Length > 0);
bool period = Regex.IsMatch(TextBoxPeriod.Text, "[1-9]{1}");
bool team = (TextBoxTeam.Text.Length > 0);
res = formclass && period && team;
}
else if ((bool)OrgBox.IsChecked)
{
bool org = (TextBoxOrg.Text.Length > 0);
res = org;
}
else
{
res = true;
}
NextButton.IsEnabled = res;
}
Visibilityでフォームの切替と、誤操作でバグらないよう丁寧に表示を切り替えます。どんな人が最初に触った時でもバグらずやりたいことができる、というのを基本方針にしてます。
そして機材入力画面のScanTagを作っていきます。まずはxaml。
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="400" />
<RowDefinition Height="150" />
</Grid.RowDefinitions>
<materialDesign:Card Margin="20,0,20,0">
<StackPanel Grid.Row="0" Orientation="Vertical" HorizontalAlignment="Right" Margin="0,0,25,0">
<StackPanel Height="80" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Style="{DynamicResource MaterialDesignTextBlock}"
VerticalAlignment="Center"
FontSize="24">機材種別:</TextBlock>
<ComboBox Grid.Row="0" x:Name="GenreComboBox"
Width="240" VerticalAlignment="Center"
FontSize="24"
SelectedValuePath="Id"
DisplayMemberPath="Name" SelectionChanged="GenreComboBox_SelectionChanged"/>
</StackPanel>
<StackPanel Height="80" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Style="{DynamicResource MaterialDesignTextBlock}"
VerticalAlignment="Center" Margin="0,0,0,0"
FontSize="24">機材名:</TextBlock>
<ComboBox Grid.Row="0" x:Name="MachineComboBox"
Width="240" VerticalAlignment="Center"
FontSize="24"
IsEnabled="False"
SelectedValuePath="Id"
DisplayMemberPath="Name" SelectionChanged="MachineComboBox_SelectionChanged"/>
</StackPanel>
<StackPanel Height="80" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Style="{DynamicResource MaterialDesignTextBlock}"
VerticalAlignment="Center" Margin="0,0,0,0"
FontSize="24">機材番号:</TextBlock>
<ComboBox Grid.Row="0" x:Name="EquipmentComboBox"
Width="240" VerticalAlignment="Center"
FontSize="24"
IsEnabled="False"
SelectedValuePath="Id"
DisplayMemberPath="Name" SelectionChanged="EquipmentComboBox_SelectionChanged"/>
</StackPanel>
<StackPanel Height="80" Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal">
<TextBlock Style="{DynamicResource MaterialDesignTextBlock}"
VerticalAlignment="Center" Margin="0,0,0,0"
FontSize="24">バッテリー数:</TextBlock>
<TextBox Margin="0,0,0,0" VerticalAlignment="Center"
Width="50" FontSize="24" x:Name="TextBoxBattery"
materialDesign:HintAssist.Hint="1個"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20,0,0,0">
<TextBlock Style="{DynamicResource MaterialDesignTextBlock}"
VerticalAlignment="Center"
FontSize="24">三脚:</TextBlock>
<TextBox Margin="0,0,0,0" VerticalAlignment="Center"
Width="100" FontSize="24" x:Name="TextBoxTripod"
materialDesign:HintAssist.Hint="大:0個"/>
</StackPanel>
</StackPanel>
<StackPanel Height="80" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Style="{DynamicResource MaterialDesignTextBlock}"
VerticalAlignment="Center" Margin="0,0,0,0"
FontSize="24">備考:</TextBlock>
<TextBox Margin="0,0,0,0" VerticalAlignment="Center"
Width="300" FontSize="24" x:Name="TextBoxRemarks"/>
</StackPanel>
</StackPanel>
</materialDesign:Card>
<Button Grid.Column="0" Grid.Row="1"
x:Name="AddButton" Content="追加する"
Style="{DynamicResource MaterialDesignRaisedLightButton}"
Width="200" Height="100" FontSize="24"
IsEnabled="False"
Click="Add_Click"/>
</Grid>
スクリーンショットの左のフォームですが、だいぶ書き方が上手くなってきました。他のページも作り直したい。インデントとかが雑なのは許してください。
ここから先はScanTag.xaml.csです。長いので分割
private ObservableCollection<Clct> _genre = new ObservableCollection<Clct>();
private ObservableCollection<Clct> _machine = new ObservableCollection<Clct>();
private ObservableCollection<Clct> _equipment = new ObservableCollection<Clct>();
private void CreateComboBox()
{
using (SQLiteConnection conn = new SQLiteConnection("Data Source=MdiSyS.db"))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Genre";
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
_genre.Add(new Clct()
{
Id = reader["GenreId"].ToString(),
Name = reader["GenreName"].ToString()
});
}
}
conn.Close();
}
GenreComboBox.ItemsSource = _genre;
}
private void GenreComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MachineComboBox.SelectedIndex = -1;
_machine.Clear();
EquipmentComboBox.IsEnabled = false;
if (GenreComboBox.SelectedIndex == -1)
{
MachineComboBox.IsEnabled = false;
return;
}
else
{
MachineComboBox.IsEnabled = true;
}
using (SQLiteConnection conn = new SQLiteConnection("Data Source=MdiSyS.db"))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Machine WHERE GenreId=" + GenreComboBox.SelectedValue;
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
_machine.Add(new Clct()
{
Id = reader["MachineId"].ToString(),
Name = reader["MachineName"].ToString() + " (" + reader["MachineDescription"].ToString() + ")"
});
}
}
conn.Close();
}
MachineComboBox.ItemsSource = _machine;
}
private void MachineComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
EquipmentComboBox.SelectedIndex = -1;
_equipment.Clear();
if (MachineComboBox.SelectedIndex == -1)
{
EquipmentComboBox.IsEnabled = false;
return;
}
else
{
EquipmentComboBox.IsEnabled = true;
}
using (SQLiteConnection conn = new SQLiteConnection("Data Source=MdiSyS.db"))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Equipment WHERE MachineId=" + MachineComboBox.SelectedValue;
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if(reader["IsLending"].ToString() == "false")
{
_equipment.Add(new Clct()
{
Id = reader["EquipmentId"].ToString(),
Name = "No." + reader["EquipmentId"].ToString() + " (" + reader["EquipmentRemarks"].ToString() + ")"
});
}
}
}
conn.Close();
}
List<Select> tempList = GridList.Where(x => x._MachineId == MachineComboBox.SelectedValue.ToString()).ToList();
foreach (var item in tempList)
{
_equipment.Remove(_equipment.Where(i => i.Id == item._EquipmentId).Single());
}
EquipmentComboBox.ItemsSource = _equipment;
}
private void EquipmentComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
AddButton.IsEnabled = (EquipmentComboBox.SelectedIndex != -1);
}
ページ読み込み時にCreateComboBox()で機材種別のComboBoxにデータを入れます。これはGenreテーブルから持ってきます。Clctは前作ったGakubuクラスの名前を変えたものです。
そしてGenreComboBoxが変更されたとき、機材名と機材番号をリセットし、選ばれてる機材種別が空白じゃなければ、その種別の機材名をデータベースから持ってきてMachineComboBoxに入れます。
これと同じことをMachineComboBox変更時にもします。ここでは、既に選択されている機材番号を削除する処理を最後にしています。
ここで使っているMachineComboBox.SelectedValueが便利だった。というかこれまでめんどくさいやり方をしていた。こういうのを調べるのが意外と難しい。。。
EquipmentComboBoxは変更時に空白じゃなければ追加ボタンを有効にします。
public class Select
{
public string _Machine { get; set; }
public string _MachineId { get; set; }
public string _Equipment { get; set; }
public string _EquipmentId { get; set; }
public string _Remarks { get; set; }
}
private void Add_Click(object sender, RoutedEventArgs e)
{
string remarks = ((TextBoxBattery.Text.Length > 0) ? "バッテリー:" + TextBoxBattery.Text + " " : "") +
((TextBoxTripod.Text.Length > 0) ? "三脚:" + TextBoxTripod.Text + " " : "") +
"備考:" + ((TextBoxRemarks.Text.Length > 0) ? TextBoxRemarks.Text : "なし");
GridList.Add(new Select()
{
_Machine = ((Clct)MachineComboBox.SelectedItem).Name,
_MachineId = ((Clct)MachineComboBox.SelectedItem).Id,
_Equipment = ((Clct)EquipmentComboBox.SelectedItem).Name,
_EquipmentId = ((Clct)EquipmentComboBox.SelectedItem).Id,
_Remarks = remarks
});
GenreComboBox.SelectedIndex = -1;
TextBoxBattery.Text = "";
TextBoxTripod.Text = "";
TextBoxRemarks.Text = "";
NextButton.IsEnabled = true;
}
private void Next_Click(object sender, RoutedEventArgs e)
{
foreach(var item in GridList)
{
FormData.EquipmentList = new List<FormData.Equipment>();
FormData.EquipmentList.Add(new FormData.Equipment()
{
MachineId = item._MachineId,
EquipmentId = item._EquipmentId,
Remarks = item._Remarks
});
}
Confirm page = new Confirm()
{
FormData = FormData
};
NavigationService.Navigate(page);
}
追加ボタンと次ページにデータ渡す処理。
ここでは日記.3の疑問を解決することができました。MachineComboBox.SelectedItem.Nameができない、という疑問でしたが、((Clct)MachineComboBox.SelectedItem).NameのようにSelectedItemをしっかりキャストしてあげるとうまくいきました。
ここまで来て、とんでもないミスがあって悲しくなりました。
🤔...
これ、自動入力で勝手にミスが広がって修正が大変でした。気を付けよう...
そもそも変数名のつけ方が下手すぎるので勉強したいわね。。
さいごに
完成しそうでなかなか完成しない。まだ1/3ぐらいな気がするのでがんばりたい。
うにてぃも触りたい。いつまで学校オンライン授業なのかな。夏休みまでとかだったら何かしらは出来そう。
リングフィット抽選販売、落選!w
900台に応募20万件って何事ですか???
この記事が気に入ったらサポートをしてみませんか?