I am trying to create a table whose cells are dynamic in width and height. Following is my xaml code:
<ItemsControl Grid.Row="1" Grid.Column="1" DataContext="{Binding GameBoardApp}" ItemsSource="{Binding BlockList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Row" Value="{Binding Row}"/>
<Setter Property="Grid.Column" Value="{Binding Col}"/>
<Setter Property="Grid.Width" Value="{Binding Width, Mode=TwoWay}" />
<Setter Property="Grid.Height" Value="{Binding Height, Mode=TwoWay}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="Black">
<Grid>
<Rectangle Fill="{Binding Background}" />
<TextBlock Text="{Binding Name}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I am able to design the UI and see the content but I am not able to set up 2-way data binding to change the width of the cell. Following is my Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
GameBoardApp = new GameBoard(50);
DataContext = this;
}
public GameBoard GameBoardApp { get; set; }
private void IncreaseSize_Click(object sender, RoutedEventArgs e)
{
GameBoardApp = new GameBoard(GameBoardApp.CellWidth + 1);
Debug.Print(GameBoardApp.CellWidth.ToString());
}
private void DecreaseSize_Click(object sender, RoutedEventArgs e)
{
GameBoardApp = new GameBoard(GameBoardApp.CellWidth-1);
Debug.Print(GameBoardApp.CellWidth.ToString());
}
}
public class GameBoard : INotifyPropertyChanged
{
public GameBoard(int cellWidthVal)
{
_cellWidth = cellWidthVal;
var m1 = new Block() { Name = "b1", Background = Brushes.Red, Col = 50, Row = 50, Width = CellWidth };
var m2 = new Block() { Name = "b2", Background = Brushes.Gray, Col = 50, Row = 50, Width = CellWidth };
var m3 = new Block() { Name = "b3", Background = Brushes.Goldenrod, Col = 0, Row = 0, Width = CellWidth };
var m4 = new Block() { Name = "b4", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
var m5 = new Block() { Name = "b5", Background = Brushes.Bisque, Col = 70, Row = 70, Width = CellWidth };
var m6 = new Block() { Name = "b6", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
var m7 = new Block() { Name = "b7", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
var m8 = new Block() { Name = "b1", Background = Brushes.Red, Col = 0, Row = 0, Width = CellWidth };
var m9 = new Block() { Name = "b2", Background = Brushes.Gray, Col = 0, Row = 0, Width = CellWidth };
var m10 = new Block() { Name = "b3", Background = Brushes.Goldenrod, Col = 0, Row = 0, Width = CellWidth };
var m11 = new Block() { Name = "b4", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
var m12 = new Block() { Name = "b5", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
var m13 = new Block() { Name = "b6", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
var m14 = new Block() { Name = "bhg jg7", Background = Brushes.Honeydew, Col = 0, Row = 0, Width = CellWidth };
_blockList = new ObservableCollection<Block>() { m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11};
}
int _cellWidth;
public int CellWidth { get { return _cellWidth; } set { _cellWidth = value; RaisePropertyChanged("CellWidth"); } }
ObservableCollection<Block> _blockList;
public ObservableCollection<Block> BlockList { get { return _blockList; } set { _blockList = value; RaisePropertyChanged("BlockList"); } }
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string propname)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
}
}
public class Block : INotifyPropertyChanged
{
int _row;
public int Row { get { return _row; } set { _row = value; RaisePropertyChanged("Row"); } }
int _col;
public int Col { get { return _col; } set { _col = value; RaisePropertyChanged("Col"); } }
string _name;
public string Name { get { return _name; } set { _name = value; RaisePropertyChanged("Name"); } }
Brush _background;
public Brush Background { get { return _background; } set { _background = value; RaisePropertyChanged("Background"); } }
int _width = 50;
public int Width { get { return _width; } set { _width = value; RaisePropertyChanged("Width"); } }
int _height = 50;
public int Height { get { return _height; } set { _height = value; RaisePropertyChanged("Width"); } }
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(string propname)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
}
}
I am trying to refresh the ItemControl once I make the changes in GameBoard but not able to do it.
Preferably I would want to change the width with only one width variable in GameBoard class but looks like that will not be possible here
Regards
Fix your
ItemContainerStyleto target theContentPresenterand bind itsWidthandHeightproperties to your source properties:And since you are creating a new
GameBoardobject in your click event handlers, you also need to implement theINotifyPropertyChangedinterface and raise change notifications in the window:This should make your example work as expected.
As a side note, the
Grid.RowandGrid.Columnattached properties are not useful when you host your item containers in aWrapPanel.