带有WPF的C# - 创建一个可在运行时调整大小的按钮网格

时间:2016-11-22 10:17:27

标签: c# wpf xaml

我想实现以下内容:我在开头有一个空窗口,有3个按钮。当我单击按钮时,我想在窗口中生成Size*Size按钮。对于按钮1,Size=6,按钮2 Size=8和按钮3 Size=0,我认为我创建了UniformGrid并将其大小绑定到{{ 1}},所以我可以改变按钮的数量。最初,Size为0,因此无法看到任何按钮,然后当Size更改时,按钮会显示。然而,这并不起作用。我正在尝试:

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> 最初为0,Size将大小更改为6,Lvl1Command更改为8等。Lvl2Command只是一个数据结构,存储一些会影响其样式的属性按钮。怎么可以/我应该修改这个,以便当大小改变时,出现按钮的数量也会这样做?谢谢!

修改 在ViewModel构造函数中:

Fields

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

1 个答案:

答案 0 :(得分:0)

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仍然绑定到空引用。您有两个选择:

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绑定将更新。