C# 如何从viewmodel在Windows Phone 8.1的画布中生成动态按钮? 编辑:因为我有太多的建议,所以首先我考虑一步一步地改变它,所以我的第一个问题是从ViewModel获得动态按钮。
我正在写一个WP 8.1游戏应用程序。因此,从C# 如何从viewmodel在Windows Phone 8.1的画布中生成动态按钮? 编辑:因为我有太多的建议,所以首先我考虑一步一步地改变它,所以我的第一个问题是从ViewModel获得动态按钮。,c#,wpf,xaml,data-binding,win-universal-app,C#,Wpf,Xaml,Data Binding,Win Universal App,我正在写一个WP 8.1游戏应用程序。因此,从MainPage.xaml我的游戏导航到GamePage.xaml。在OnNavigatedTo方法中,我有这样一个代码 protected override void OnNavigatedTo(NavigationEventArgs e) { // Initialize GamePageViewModel gmPageViewModel = new GamePageViewModel(this); this.DataCon
MainPage.xaml
我的游戏导航到GamePage.xaml
。在OnNavigatedTo
方法中,我有这样一个代码
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Initialize GamePageViewModel
gmPageViewModel = new GamePageViewModel(this);
this.DataContext = gmPageViewModel;
}
首先,在视图中,我为网格设置了DataContext,我将DataContext设置为
<Grid
DataContext="{Binding GamePageVM, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<StackPanel Orientation="Horizontal" Grid.Row="1" >
<TextBlock Text="{Binding Value, Mode=TwoWay}"/>
<TextBlock Text="{Binding Moves, Mode=TwoWay}" />
</StackPanel>
<Canvas x:Name="GameCanvas" Grid.Row="2"
DataContext="{Binding ButtonItems,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay}">
<ItemsControl >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding TopLeftX}"/>
<Setter Property="Canvas.Top" Value="{Binding TopLeftY}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="{Binding Width}"
Height="{Binding Height}"
Command="{Binding ButtonClickCommand}"
CommandParameter="{Binding Content,
RelativeSource={RelativeSource Self}}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</Grid>
GameObject是一个生成一些唯一随机数的对象
现在是InItBoard(),我在这里创建动态按钮ButtonItems
private void initTheBoard()
{
buttonItems = new ObservableCollection<ButtonPosition>();
Random r = new Random();
List<ButtonPosition> buttonPositions = new List<ButtonPosition>();
Button button;
for (int i = 0; i < numOfButtons; i++)
{
button = new Button();
bool foundOverlap = false;
int left;
int top;
ButtonPosition bp;
do
{
foundOverlap = false;
// Create a new random position for the button (subtracting the width/height
// from the X,Y so that we don't overlap the edge of the canvas)
left = r.Next(0, 500 - buttonWidth - 10);
top = r.Next(0, 500 - buttonHeight - 10);
bp = new ButtonPosition(left, top, buttonWidth, buttonHeight);
// Check each of the existing buttons for overlap
foreach (ButtonPosition existingButton in buttonPositions)
{
if (bp.Overlaps(existingButton))
{
foundOverlap = true;
break;
}
}
} while (foundOverlap);
buttonItems.Add(bp);
buttonPositions.Add(bp);
}
}
gamePageVM = this;
此高度、宽度、TopLeftX和TopLeftY绑定到按钮的Datatemplate。
任何帮助,为什么按钮没有加载到画布中 如果您只想替换视图模型中的
GamePage
对象,则向视图模型中添加一个接受GamePage
的方法
public void ReplaceGamePage(GamePage page)
{
this.GamePage = page;
}
如果视图模型上的GamePage属性在连接事件时发生了更改,您的视图将被刷新。另一种方法是强制刷新视图上的数据上下文。在代码隐藏单击事件处理程序中,可以引发属性更改事件
this.OnPropertyChanged(new DependencyPropertyChangedEventArgs(this.DataContext, this.DataContext, new GamePage()));
这将刷新DataContext绑定,强制视图使用视图模型更新其所有绑定
但是,我强烈建议您停止将视图特定的内容混合到视图模型中。MVVM是一条单行道。视图模型不应该知道视图元素,只为要绑定到的视图提供数据
您应该做的是将按钮隐藏在模型后面,给每个模型一个随机的X/Y位置,然后将模型集合绑定到视图上的ItemsControl。可以在模型中定义的X/Y值处为模型指定一个DataTemplate,将每个模型渲染为一个按钮。这将使您可以将命令连接到视图模型,并消除对代码隐藏的需要。经过大量时间和尝试许多选项后,我终于发现了问题,让我告诉您问题是什么 在WPF中
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=TopLeftX}" />
<Setter Property="Canvas.Top" Value="{Binding Path=TopLeftY}" />
</Style>
</ItemsControl.ItemContainerStyle>
我们还需要做一个改变
<ItemsControl.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<Setter Property="Canvas.Left" Value="{Binding Path=TopLeftX}" />
<Setter Property="Canvas.Top" Value="{Binding Path=TopLeftY}" />
</Style>
</ItemsControl.ItemContainerStyle>
我们必须为Silverlight使用FrameworkElement
,而不是ContentPresenter
这就是我想要的解决方案。它就像一个符咒
ReplaceGamePage
将位于viewModel中并接受参数GamePage,但在我的viewModel中没有GamePage
的属性,并且单击事件处理程序不在viewModel中其后面的代码中。DependencyPropertyChangedEventArgs(this.DataContext,this.DataContext,new GamePage())给出了一个错误,它的构造函数不包含三个参数。按钮模型建议尝试一下,问题是我根据游戏标签随机选择的按钮编号。因此,我们面临着困难,主要关注点是动态刷新游戏页面,并在画布中添加一些动画,当用户单击按钮时,根本不应该将视图传递给视图模型。ViewModel不应该知道视图实例存在。如果使用MVVM模式,则可以在不向视图模型提供视图引用的情况下实现这一点。视图模型仍然可以根据标签数据绑定到的字符串属性为模型指定随机数。视图模型中没有标签
引用。向视图添加标签,将其绑定到视图模型上的字符串属性,并让视图模型根据字符串属性为模型生成编号。然后,您的视图可以通过模板从模型集合中创建按钮,如我的回答中所述。我已经更新了我的问题,我想如果我能够按照您的建议从ViewModel填充视图,我可以获得刷新UI功能,但仍然无法使其工作,我已经发布了所有可能的代码。你能找出是什么错吗?
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=TopLeftX}" />
<Setter Property="Canvas.Top" Value="{Binding Path=TopLeftY}" />
</Style>
</ItemsControl.ItemContainerStyle>
<Button.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding TopLeftX}" Y="{Binding TopLeftY}" />
</TransformGroup>
</Button.RenderTransform>
<ItemsControl.ItemContainerStyle>
<Style TargetType="FrameworkElement">
<Setter Property="Canvas.Left" Value="{Binding Path=TopLeftX}" />
<Setter Property="Canvas.Top" Value="{Binding Path=TopLeftY}" />
</Style>
</ItemsControl.ItemContainerStyle>