アイデアは次のとおりです。4 つの行でグリッドを構築し、それぞれに 1 つのグラフがあります。Grid.RowSpan を 4 に設定して、分割ボタンとして 3 つの四角形をグリッドに追加します。
MainWindow.xaml:
<Window x:Class="testwpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
MouseMove="Window_MouseMove_1" MouseUp="Window_MouseUp_1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Name="row1" Height="40"/>
<RowDefinition Name="row2" Height="40"/>
<RowDefinition Name="row3" Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="Green"/>
<Rectangle Grid.Row="1" Fill="Blue"/>
<Rectangle Grid.Row="2" Fill="Red"/>
<Rectangle Grid.Row="3" Fill="Yellow"/>
<Rectangle Fill="#5000" VerticalAlignment="Top" Height="10" Name="splitter1" MouseDown="splitter_MouseDown_1" Grid.RowSpan="4" Margin="0,40,0,0"/>
<Rectangle Fill="#5000" VerticalAlignment="Top" Height="10" Name="splitter2" MouseDown="splitter_MouseDown_1" Grid.RowSpan="4" Margin="0,80,0,0"/>
<Rectangle Fill="#5000" VerticalAlignment="Top" Height="10" Name="splitter3" MouseDown="splitter_MouseDown_1" Grid.RowSpan="4" Margin="0,120,0,0"/>
</Grid>
</Window>
MainWindow.xaml.cs:
FrameworkElement dragginSplitter = null;
private void splitter_MouseDown_1(object sender, MouseButtonEventArgs e)
{
dragginSplitter = sender as FrameworkElement;
}
private void Window_MouseMove_1(object sender, MouseEventArgs e)
{
if (dragginSplitter != null)
dragginSplitter.Margin = new Thickness(0, e.GetPosition(this).Y, 0, 0);
if (splitter2.Margin.Top < splitter1.Margin.Top + 10) splitter2.Margin = new Thickness(0, splitter1.Margin.Top + 10, 0, 0);
if (splitter3.Margin.Top < splitter2.Margin.Top + 10) splitter3.Margin = new Thickness(0, splitter2.Margin.Top + 10, 0, 0);
row1.Height = new GridLength(splitter1.Margin.Top);
row2.Height = new GridLength(splitter2.Margin.Top - splitter1.Margin.Top);
row3.Height = new GridLength(splitter3.Margin.Top - splitter2.Margin.Top);
}
private void Window_MouseUp_1(object sender, MouseButtonEventArgs e)
{
dragginSplitter = null;
}
Window_MouseMove_1 に関する重要な注意事項:
- スプリッターがドラッグされるたびに、dragingSplitter の上部マージンは、マウスの Y 位置に等しくなります。
- スプリッターは互いにすれ違うべきではないため、スプリッターがドラッグされるたびに上部マージンをチェックします。
- グリッドの行の高さ (グリッドの内容ではありません) は、スプリッターがドラッグされるたびに、スプリッターの上余白に従って計算されます。
編集:
非表示/表示のニーズを満たすために、コードを変更し、さまざまな条件を追加しました。
<Window x:Class="testwpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
MouseMove="Window_MouseMove_1" MouseUp="Window_MouseUp_1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Name="row1" Height="40"/>
<RowDefinition Name="row2" Height="40"/>
<RowDefinition Name="row3" Height="40"/>
<RowDefinition Name="row4" Height="*"/>
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="Green"/>
<Rectangle Grid.Row="1" Fill="Blue"/>
<Rectangle Grid.Row="2" Fill="Red"/>
<Rectangle Grid.Row="3" Fill="Yellow"/>
<Rectangle Fill="#5000" VerticalAlignment="Top" Height="10" Name="splitter1" MouseDown="splitter_MouseDown_1" Grid.RowSpan="4" Margin="0,40,0,0"/>
<Rectangle Fill="#5000" VerticalAlignment="Top" Height="10" Name="splitter2" MouseDown="splitter_MouseDown_1" Grid.RowSpan="4" Margin="0,80,0,0"/>
<Rectangle Fill="#5000" VerticalAlignment="Top" Height="10" Name="splitter3" MouseDown="splitter_MouseDown_1" Grid.RowSpan="4" Margin="0,120,0,0"/>
<WrapPanel Grid.RowSpan="4">
<CheckBox Name="check1" Content="graph1" IsChecked="True" Checked="CheckBox_Checked_1" Unchecked="CheckBox_Checked_1"/>
<CheckBox Name="check2" Content="graph2" IsChecked="True" Checked="CheckBox_Checked_1" Unchecked="CheckBox_Checked_1"/>
<CheckBox Name="check3" Content="graph3" IsChecked="True" Checked="CheckBox_Checked_1" Unchecked="CheckBox_Checked_1"/>
<CheckBox Name="check4" Content="graph4" IsChecked="True" Checked="CheckBox_Checked_1" Unchecked="CheckBox_Checked_1"/>
</WrapPanel>
</Grid>
</Window>
xaml の変更: 4 つのチェックボックスが追加され、4 行目に名前が付けられます。
FrameworkElement dragginSplitter = null;
private void splitter_MouseDown_1(object sender, MouseButtonEventArgs e)
{
dragginSplitter = sender as FrameworkElement;
}
private void Window_MouseMove_1(object sender, MouseEventArgs e)
{
if (dragginSplitter != null)
{
dragginSplitter.Margin = new Thickness(0, e.GetPosition(this).Y, 0, 0);
updateSplitters();
}
}
private void updateSplitters()
{
if (splitter2.Margin.Top < splitter1.Margin.Top + 10) splitter2.Margin = new Thickness(0, splitter1.Margin.Top + 10, 0, 0);
if (splitter3.Margin.Top < splitter2.Margin.Top + 10) splitter3.Margin = new Thickness(0, splitter2.Margin.Top + 10, 0, 0);
if (check1.IsChecked.Value)
{
if (!check2.IsChecked.Value && !check3.IsChecked.Value && !check4.IsChecked.Value)
row1.Height = new GridLength(1, GridUnitType.Star);
else
row1.Height = new GridLength(splitter1.Margin.Top);
}
else
row1.Height = new GridLength(0);
if (check2.IsChecked.Value)
{
if (!check3.IsChecked.Value && !check4.IsChecked.Value)
row2.Height = new GridLength(1, GridUnitType.Star);
else if(check1.IsChecked.Value)
row2.Height = new GridLength(splitter2.Margin.Top - splitter1.Margin.Top);
else
row2.Height = new GridLength(splitter2.Margin.Top);
}
else
row2.Height = new GridLength(0);
if (check3.IsChecked.Value)
{
if (!check4.IsChecked.Value)
row3.Height = new GridLength(1, GridUnitType.Star);
else if (check2.IsChecked.Value)
row3.Height = new GridLength(splitter3.Margin.Top - splitter2.Margin.Top);
else if (check1.IsChecked.Value)
row3.Height = new GridLength(splitter3.Margin.Top - splitter1.Margin.Top);
else
row3.Height = new GridLength(splitter3.Margin.Top);
}
else
row3.Height = new GridLength(0);
row4.Height = check4.IsChecked.Value ? new GridLength(1, GridUnitType.Star) : new GridLength(0);
}
private void Window_MouseUp_1(object sender, MouseButtonEventArgs e)
{
dragginSplitter = null;
}
private void CheckBox_Checked_1(object sender, RoutedEventArgs e)
{
if (check4 == null) return;//for when not yet completely loaded
if (!check1.IsChecked.Value)
splitter1.Visibility = System.Windows.Visibility.Collapsed;
if (!check2.IsChecked.Value)
splitter2.Visibility = System.Windows.Visibility.Collapsed;
if (!check3.IsChecked.Value)
splitter3.Visibility = System.Windows.Visibility.Collapsed;
if (!check4.IsChecked.Value)
{
splitter3.Visibility = System.Windows.Visibility.Collapsed;
if (!check3.IsChecked.Value)
splitter2.Visibility = System.Windows.Visibility.Collapsed;
if (!check2.IsChecked.Value)
splitter1.Visibility = System.Windows.Visibility.Collapsed;
}
if (check1.IsChecked.Value && (check2.IsChecked.Value || check3.IsChecked.Value || check4.IsChecked.Value))
splitter1.Visibility = System.Windows.Visibility.Visible;
if (check2.IsChecked.Value && (check3.IsChecked.Value || check4.IsChecked.Value))
splitter2.Visibility = System.Windows.Visibility.Visible;
if (check3.IsChecked.Value && check4.IsChecked.Value)
splitter3.Visibility = System.Windows.Visibility.Visible;
updateSplitters();
}
cs の変更:
- updateSplitters 関数は、スプリッターのマージンを更新するための以前のロジックに置き換えられます。
- チェックボックスをオンまたはオフにすると、スプリッターの可視性が変化し、updateSplitters が呼び出されます。
- updateSplitters が残りのすべてを行います。グリッドの残りのスペースを埋めるために、最後に表示される行の GridUnitType が常に Star であることを除いて、多くはありません。
私が見つけた唯一の問題は、ウィンドウのサイズが変更されているとき、または上の行の 1 つが大きな Height 値にサイズ変更されているときに、Grid の下部の内容が画面からはみ出す可能性があることです。