2

私のアプリは、mainpage.xaml に配置される 20 個のボタンのリストを作成します。

private List<Button> CreateList()
    {
        for (int i = 0; i <= 19; i++)
        {
            string name = string.Format("button{0}", i+1);

            Button buttt = new Button();
            buttt.Name = name;
            buttt.Content = i + 1;
            buttt.Height = 72;
            buttt.HorizontalAlignment = HorizontalAlignment.Left;
            buttt.VerticalAlignment = VerticalAlignment.Top;
            buttt.Width = 88;
            buttt.Click += new RoutedEventHandler(this.button_Click);
            GameGrid.Children.Add(buttt);

            myList.Insert(i, buttt);
        }

このリストをシャッフルしようとすると、ページ上の実際のボタンへの接続が失われるようです。

private void Shuffle(List<Button> list)
    {
        //list[1].Content = "DING!";

        Random rand = new Random();
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = rand.Next(n + 1);
            Button value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }

//list[1].Content = "DING!";このメソッドの残りの部分をコメント解除してコメントアウトすると、ボタンのコンテンツが画面上で変更されることに注意してください。したがって、シャッフル中にリンクが壊れていると思います。

したがって、私の問題は、このコードを実行すると、ボタンが表示されますが、意図したようにランダムにシャッフルされるのではなく、1 から 20 までの順序で表示されることです。

助けてくれてありがとう!

編集:クリスの提案を含む完全なコードは次のとおりです。

private List<Button> CreateList(List<Marginz> myMargin)
    {
        for (int i = 0; i <= 19; i++)
        {
            string name = string.Format("button{0}", i+1);

            Button buttt = new Button();
            buttt.Name = name;
            buttt.Content = i + 1;
            buttt.Height = 72;
            buttt.HorizontalAlignment = HorizontalAlignment.Left;
            buttt.VerticalAlignment = VerticalAlignment.Top;
            buttt.Width = 88;
            buttt.Click += new RoutedEventHandler(this.button_Click);
            Thickness myThickness = new Thickness();
            myThickness.Left = myMargin[i].left;
            myThickness.Top = myMargin[i].top;
            myThickness.Right = myMargin[i].right;
            myThickness.Bottom = myMargin[1].bottom;
            buttt.Margin = myThickness;
            //GameGrid.Children.Add(buttt);

            myList.Insert(i, buttt);
        }

        return myList;
    }

そして、ここでそれが呼び出されます:

private void EasyButton_Click(object sender, RoutedEventArgs e)
    {
        DifficultyCanvas.Visibility = System.Windows.Visibility.Collapsed;
        ReadyCanvas.Visibility = System.Windows.Visibility.Visible;

        //set difficulty attributes
        difficulty = "Easy";

        var myMarg = CreateMarginList(marg);
        var buttons = CreateList(myMarg);
        Shuffle(buttons);

        foreach (var button in buttons)
        {
            GameGrid.Children.Add(button);
        }
    }

詳細な説明のために編集: 余白について。Marginz というクラスを作成しました。

public class Marginz
    {
        public Marginz()
        {
            //Constructor
        }
        public int left { get; set; }
        public int top { get; set; }
        public int right { get; set; }
        public int bottom { get; set; }
    }

「marg」は次のタイプのリストです。

List<Marginz> marg = new List<Marginz>(20);

そして CreateMarginList() はこれを行います:

public List<Marginz> CreateMarginList(List<Marginz> myMarg)
    {
        Marginz one = new Marginz();
        one.left = 28;
        one.top = 186;
        one.right = 0;
        one.bottom = 0;
        myMarg.Insert(0, one);

        Marginz two = new Marginz();
        two.left = 133;
        two.top = 186;
        two.right = 0;
        two.bottom = 0;
        myMarg.Insert(1, two);

などなど、20 までずっと。次にreturn myMarg; 、すべてのボタンには、グリッドに配置する一意のマージンがあります。

これは私が今持っているものです:

4

3 に答える 3

1

myList コレクションをシャッフルしても、ページに表示される順序は変わりません。これは、CreateList メソッドでそれらを GameGrid に追加する順序によって決定されます。代わりにできることは、それらをすべて作成し、リストをシャッフルしてから、それらを Children リストに追加することです

GameGrid.Children.Addそのため、呼び出しを削除しますCreateList(注、コードを少し調整しました。完全なコードを投稿していないと仮定しています)

private List<Button> CreateList()
{
    var myList = new List<Button>();

    for (int i = 0; i <= 19; i++)
    {
        string name = string.Format("button{0}", i+1);

        Button buttt = new Button();
        buttt.Name = name;
        buttt.Content = i + 1;
        buttt.Height = 72;
        buttt.HorizontalAlignment = HorizontalAlignment.Left;
        buttt.VerticalAlignment = VerticalAlignment.Top;
        buttt.Width = 88;
        buttt.Click += new RoutedEventHandler(this.button_Click);

        myList.Add(buttt);
    }

    return myList;
}

シャッフルを実行してから追加します。

var buttons = CreateList();
Shuffle(buttons);

foreach(var button in buttons)
{
    GameGrid.Children.Add(button);
}

編集:投稿した完全なコードから、問題はすべてのボタンがGridコントロール内にあるため、それらの配置がどの行/列にあるか、およびそのMarginセル内の配置を制御することによって決定されることです)。行/列を明示的に定義しない場合は、最初の行/列にあると見なされます。この場合、シャッフルされていない余白が配置を決定します。

この場合、セルを使用してグリッドを構築するか、おそらく最も簡単に、myMarginリストを作成する前にリストをシャッフルするだけだと思います! ボタンは順番に追加されますが、配置はランダムになります。

var myMargin = CreateMargins(); //wherever that's done
Shuffle(myMargin); //you'll have to change the signature to work against List<Thickness> instead
var buttons = CreateList(myMargin); //add back the GameGrid.Children.Add call
//notice, no longer a call to shuffle the buttons

最善の解決策ではないかもしれませんが、これはあなたが求めていたのと同じ効果をもたらすと思います.

于 2013-01-13T20:37:17.757 に答える
0

のボタンのインデックスをシャッフルすることもできますがUIElementCollection、コードですべてのマージンを明示的に設定するとシャッフルできないため、グリッド タイプを切り替える必要がある場合があります。

を使用StackPanelWrapPanelたりUniformGrid、コントロールをレイアウトしたりできますか??

例に基づいていますUniformGrid(コントロールにマージンを設定していない限り、すべてのグリッドで同じことが機能します)。

現在の質問に対する回答ではないことは承知していますが、正しい方向に向けられるかもしれません。

private void Shuffle(UIElementCollection list)
{
    Random rand = new Random();
    int n = list.Count;
    while (n > 1)
    {
        n--;
        int k = rand.Next(n + 1);
        Button value = list.OfType<Button>().ElementAt(n);
        list.Remove(value);
        list.Insert(k, value);
    }
}

例:

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="199" Width="206" Name="UI">
    <Grid>
        <UniformGrid Name="GameGrid" Margin="0,48,0,0" Height="112" VerticalAlignment="Top">
            <Button Content="Button 1" />
            <Button Content="Button 2" />
            <Button Content="Button 3" />
            <Button Content="Button 4" />
            <Button Content="Button 5" />
        </UniformGrid>
        <Button Content="Shuffle" Height="23" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>

コード:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Shuffle(GameGrid.Children);
    }

    private void Shuffle(UIElementCollection list)
    {
        Random rand = new Random();
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = rand.Next(n + 1);
            Button value = list.OfType<Button>().ElementAt(n);
            list.Remove(value);
            list.Insert(k, value);
        }
    }
}
于 2013-01-13T22:06:54.507 に答える
0

あなたの論理には欠陥があります。ボタンをグリッドに配置し、余白を付けて配置します。マージンを使用して配置しているため、グリッドに追加する順序に関係なく、位置は変わりません。

あなたがやろうとしていることをするためのいくつかの方法:

  • ボタン リストがシャッフルされたに余白を適用する
  • グリッドの代わりに Stackpanel を使用する (そして余白を削除する)
  • 意図したとおりにグリッドを使用します: いくつかの行を作成し、各ボタンを行に割り当てます

    <Grid>
        <Grid.RowDefinitions>
            <Grid.RowDefinition />
            <Grid.RowDefinition />
            <Grid.RowDefinition />
            etc...
        </Grid.RowDefinitions>
    <Grid>
    

    次に、コード ビハインドで、各ボタンの行を設定します。

    Grid.SetRow(myButton, 1);
    
于 2013-01-13T21:49:01.360 に答える