我正在学习WPF,并尝试创建一个完全可换肤的可配置步步高板。 该板包含许多引脚,这些引脚源自网格并包含许多椭圆(棋子)。引脚放置在另一个网格'MainGrid'上,该网格基本上是电路板。 用于创建引脚的参数作为字符串存储在资源目录中。该字符串实际上是电路板的附加属性。 (配置示例仅显示两个条形针的配置)
<Style x:Key="MainGrid_style" TargetType="Grid">
// ...
<Setter Property="bgb:BgBoard.BarParams" Value="Bottom,5,8,1,1,4/Top,5,8,6,1,4"/>
</Style>
样式应用于主网格,如下所示:
<Grid x:Name="MainGrid" Style="{DynamicResource MainGrid_style}">
我的电路板编码如下:
public partial class BgBoard : Window
{
public static DependencyProperty BarParamsProperty = DependencyProperty.RegisterAttached("BarParams", typeof(string),
typeof(BgBoard), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(BarParamsPropertyChanged)));
public static string GetBarParams(Grid Grid) { return Convert.ToString(Grid.GetValue(BarParamsProperty)); }
public static void SetBarParams(Grid Grid, string Value) { Grid.SetValue(BarParamsProperty, Value); }
private static void BarParamsPropertyChanged(Object Sender, DependencyPropertyChangedEventArgs e)
{
Grid Grid = (Grid)Sender;
string[] sBarParams = GetBarParams(Grid).Split('/');
for (int player = 0; player <= 1; player++)
{
// *** sBarParams[player] is further parsed and parameters are determined
BgPin pin = new BgPin(type, size);
// *** Set the other pin params
pin.Name = "Bar" + player;
Grid.Children.Add(pin);
}
}
这完美地工作,并按预期将两个条形针脚放在电路板上。 但是,现在我希望能够将两个引脚作为数组引用(_Bar [0]和_Bar [1])
所以我在主板上添加了以下字段:
private BgPin[] _Bar = new BgPin[2];
我无法通过附加属性实例化或分配这些引脚,因为BarParamsPropertyChanged方法是静态的。
所以在我的Board的构造函数中,我添加了:
public BgBoard()
{
InitializeComponent();
_Bar[0] = (BgPin)MainGrid.FindName("Bar0");
}
但是,这不起作用,因为_Bar [0]在此指令后仍为空。我有什么想法可以引用名为“Bar0”的对象作为_Bar [0]?任何解决方案都可以。它不需要通过'name'-property工作。
答案 0 :(得分:0)
你可以这样试试:
BgPin
创建后调用的逻辑BgPin
)中,调用静态事件以便调用subscriber方法BarParamsPropertyChanged
)实现BgBoard
,并在IDisposable
方法实现中取消订阅静态事件中的非静态方法。需要执行此步骤以确保类的实例可以正确地进行GC编辑。例如(未经测试):
Dispose
答案 1 :(得分:0)
在代码隐藏中创建GUI元素并不是WPF的设计方式。您应该创建数据模型来表示您的电路板,然后使用数据绑定在视图中显示该数据。要查看一个很好的示例,请查看my answer to another SO question about displaying a chess board。
答案 2 :(得分:0)
自己找到解决方案。我在静态方法中添加了以下代码:
BgBoard Board = (BgBoard)Grid.Parent;
Board._Bar[player] = pin;
这是完整的编码: 皮肤文件的XAML:
<Style x:Key="MainGrid_style" TargetType="Grid">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="pack://SiteOfOrigin:,,,/Graphics/WoodBoard.jpg"/>
</Setter.Value>
</Setter>
<Setter Property="bgb:BgBoard.GridRows" Value="44*,45*,45*,20*,44*,48*,44*,20*,45*,45*,44*"/>
<Setter Property="bgb:BgBoard.GridColumns" Value="36*,30*,30*,30*,30*,30*,30*,2*,30*,1*,30*,30*,30*
,30*,30*,30*,13*,33*,36*,22*,37*,4*,37*,20*,30*"/>
<Setter Property="bgb:BgBoard.BarParams" Value="Bottom,5,8,1,1,4/Top,5,8,6,1,4"/>
</Style>
XAML BgBoard
<Grid x:Name="MainGrid" Style="{DynamicResource MainGrid_style}">
Codebehind BgBoard
public partial class BgBoard : Window
{
public static DependencyProperty BarParamsProperty = DependencyProperty.RegisterAttached("BarParams", typeof(string),
typeof(BgBoard), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None,
new PropertyChangedCallback(BarParamsPropertyChanged)));
public static string GetBarParams(Grid Grid) { return Convert.ToString(Grid.GetValue(BarParamsProperty)); }
public static void SetBarParams(Grid Grid, string Value) { Grid.SetValue(BarParamsProperty, Value); }
private static void BarParamsPropertyChanged(Object Sender, DependencyPropertyChangedEventArgs e)
{
Grid Grid = (Grid)Sender;
string[] sBarParams = GetBarParams(Grid).Split('/');
for (int player = (int)Player.Player1; player <= (int)Player.Player2; player++)
{
string[] sBarParam = sBarParams[player].Split(',');
string type = sBarParam[0];
int size = Convert.ToInt32(sBarParam[1]);
int column = Convert.ToInt32(sBarParam[2]);
int row = Convert.ToInt32(sBarParam[3]);
int columnspan = Convert.ToInt32(sBarParam[4]);
int rowspan = Convert.ToInt32(sBarParam[5]);
BgPin pin = new BgPin(type, size);
Grid.SetColumn(pin, column);
Grid.SetRow(pin, row);
Grid.SetColumnSpan(pin, columnspan);
Grid.SetRowSpan(pin, rowspan);
pin.Player = (Player)player;
Grid.Children.Add(pin);
BgBoard Board = (BgBoard)Grid.Parent;
Board._Bar[player] = pin;
}
}
private BgPin[] _Bar = new BgPin[2];
public BgBoard()
{
InitializeComponent();
_Bar[0].Checkers = 3;
}
这样就可以让玩家1的3个棋子出现在栏上,就像我想要的那样。