[英]C# with WPF - Creating a grid of buttons resizable at runtime
我要实现以下目的:我有一个空的窗口,开头有3个按钮。 单击按钮时,我想在窗口中生成“ Size*Size
按钮。 对于按钮1, Size=6
,对于按钮2 Size=8
,对于按钮3 Size=0
,所以我认为我将创建一个UniformGrid
并将其大小绑定到Size
,以便可以更改当前按钮的数量。 最初,“ Size
为0,因此看不到任何按钮,然后在“ Size
更改时出现按钮。 但是,这不起作用。 我正在努力:
<Window x:Class="project.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="500" Width="700">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Menu Grid.Column="1" Margin="38,0,187,430" Background="White">
<MenuItem Header="Level 1" FontFamily="Roboto" Height="32" Width="65"
Command="{Binding Lvl1Command}"/>
<MenuItem Header="Level 2" FontFamily="Roboto" Height="32" Width="65"
Command="{Binding Lvl2Command}"/>
<MenuItem Header="Level 3" FontFamily="Roboto" Height="32" Width="65"
Command="{Binding Lvl3Command}"/>
</Menu>
<ItemsControl Grid.Column="2" ItemsSource="{Binding Fields}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="{Binding Size}" Columns="{Binding Size}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Focusable="False" RenderTransformOrigin="0.5, 0.5"
Width="30" Height="25" FontSize="24" FontWeight="Bold">
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
Size
最初为0, Lvl1Command
将大小更改为6, Lvl1Command
更改为8, Lvl2Command
。 Fields
只是存储一些会影响按钮样式的属性的数据结构。 我如何/应该对此进行修改,以便在“大小”更改时,出现的“按钮”数量也可以更改? 谢谢!
在ViewModel构造函数中编辑 :
Lvl1Command = new DelegateCommand(param => { SetUpGame(MLModel.Level.Easy); });
Lvl2Command = new DelegateCommand(param => { SetUpGame(MLModel.Level.Medium); });
Lvl3Command = new DelegateCommand(param => { SetUpGame(MLModel.Level.Hard); });
SetUpGame()
看起来像这样(包括Field
):
private void SetUpGame(MLModel.Level level)
{
UpCommand = new DelegateCommand(param => { _model.MoveUp(); RefreshTable(); });
DownCommand = new DelegateCommand(param => { _model.MoveDown(); RefreshTable(); });
LeftCommand = new DelegateCommand(param => { _model.MoveLeft(); RefreshTable(); });
RightCommand = new DelegateCommand(param => { _model.MoveRight(); RefreshTable(); });
// időzítő létrehozása
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromSeconds(1);
_timer.Tick += new EventHandler(Timer_Tick);
_timer.Start();
_model.SetLevel(level);
_model.NewGame();
Fields = new ObservableCollection<MLField>();
for (Int32 i = 0; i < _model.Table.Size; i++)
{
for (Int32 j = 0; j < _model.Table.Size; j++)
{
Fields.Add(new MLField
{
Text = _model.Table[i, j],
X = i,
Y = j,
Number = i * _model.Table.Size + j
});
}
}
RefreshTable();
}
然后Size
:
public Int32 Size { get { return _model.Size; } }
ViewModel必须实现INotifyPropertyChanged
。 添加此代码:
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
然后,如果要引发有关Size
属性更改的通知,请按以下方式编写:
public int Size
{
get { return _Size; }
set
{
if (_Size != value)
{
_Size = value;
NotifyPropertyChanged();
}
}
}
private int _Size;
此外, Fields
集合最初为null,并且在SetupGame
实例化它时,不会引发任何通知,因此View仍绑定到null引用。 您有2个选择:
1) 在构造函数中初始化Fields集合 。 这样,将ViewModel传递给View时,可以将集合绑定到ItemsControl
。 不必将集合填充到构造函数中,只需对其进行实例化即可。
2) 以相同的方式实现Fields属性 :
public ObservableCollection<MLField> Fields
{
get { return _Fields; }
set
{
if (_Fields != value)
{
_Fields = value;
NotifyPropertyChanged();
}
}
}
private ObservableCollection<MLField> _Fields;
这样,您可以在每次需要的时候设置一个新的集合实例,并且ItemsControl绑定将随之更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.