2009-06-05 3 views
7

저는 WPF가 매우 새로워서 문법을 배우기 위해 아주 간단한 메모리 카드 게임을 만들기 시작했습니다. 게임은 모든 카드가 아래로 향하게하는 곳입니다. 뒤집어서 두 장을 뒤집고 일치하는 카드가 있으면 제거하십시오. 그렇지 않으면 카드를 다시 채우고 가장 짧은 수의 카드를 제거하십시오. 내가 말했듯이, 매우 간단하게 ... :)WPF의 테이블 레이아웃

제 질문은 HTML과 같은 테이블 요소가 없기 때문에 마진을 망칠 필요없이 유니폼 레이아웃에 카드를 쉽게 넣을 수 있습니까?

답변

10

다음은 Matt Hamilton이 제안한 UniformGrid를 사용한 예입니다.

먼저 우리가 사용할 클래스와 데이터를 만듭니다. 각 카드는 카드 객체로 표현하고, 페이스 속성이됩니다

public class Card 
{ 
    public string Face { get; set; } 
    public Card() { } 
} 

다음, 우리는 우리 카드의 수를 설정할 수 있습니다 카드의 우리의 컬렉션을 가진 클래스, 또한 속성을해야합니다을 . CardCollection의 경우 카드를 추가하거나 제거 할 때 UI에 자동으로 알리기 때문에 ObservableCollection을 사용할 수 있습니다. NumberOfCards 속성은 UI에 알리는 자체 메서드가 필요합니다.이 경우 implementINotifyPropertyChanged 인터페이스를 사용할 수 있습니다. 마지막으로

public class Cards : INotifyPropertyChanged 
{ 
    private int myNumberOfCards; 
    public int NumberOfCards 
    { 
     get { return this.myNumberOfCards; } 
     set 
     { 
      this.myNumberOfCards = value; 
      NotifyPropertyChanged("NumberOfCards"); 

      // Logic is going in here since this is just an example, 
      // Though I would not recomend hevily modifying the setters in a finalized app. 
      while (this.myNumberOfCards > CardCollection.Count) 
      { 
       CardCollection.Add(new Card { Face = (CardCollection.Count + 1).ToString() }); 
      } 
      while (this.myNumberOfCards < CardCollection.Count) 
      { 
       CardCollection.RemoveAt(CardCollection.Count - 1); 
      } 

      NotifyPropertyChanged("CardColumns"); 
     } 
    } 
    public int CardColumns 
    { 
     get 
     { 
      return (int)Math.Ceiling((Math.Sqrt((double)CardCollection.Count))); 
     } 
    } 
    private ObservableCollection<Card> myCardCollection; 
    public ObservableCollection<Card> CardCollection 
    { 
     get 
     { 
      if (this.myCardCollection == null) 
      { this.myCardCollection = new ObservableCollection<Card>(); } 
      return this.myCardCollection; 
     } 
    } 
    public Cards(int initalCards) 
    { 
     NumberOfCards = initalCards; 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
     } 
    } 

    #endregion 
} 


, 우리는 창에있는 우리의 DataContext로이 설정할 수 있습니다 : 우리는 또한 사용하는 행/열 수를 나타내는 속성을 원하는 것, 이것은 우리의 NumberOfCards의 제곱근 될 것입니다 , XAML의 Cards 클래스에 바인딩합니다. XAML의 경우 간단한 ItemsControl을 사용하여 선택할 수 없도록하고 DataTemplate을 단추로 설정하여 각 카드를 클릭하면 필요한 모든 작업을 수행 할 수 있습니다. 내가보고 권 해드립니다 것이다

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
     this.DataContext = new Cards(25); 
    } 
} 

<Window x:Class="Sample_BoolAnimation.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" 
    Height="300" 
    Width="300"> 
    <Grid> 
     <DockPanel> 
      <DockPanel DockPanel.Dock="Top"> 
       <TextBlock Text="Number of Cards:" /> 
       <TextBox Text="{Binding NumberOfCards, UpdateSourceTrigger=PropertyChanged}" /> 
      </DockPanel> 
      <ItemsControl ItemsSource="{Binding CardCollection}"> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <UniformGrid Columns="{Binding CardColumns}" /> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <Button Content="{Binding Face}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 

        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
     </DockPanel> 
    </Grid> 
</Window> 

또 다른 것은 조쉬 스미스의 ContentControl3D 구현입니다. 따라서 Card 클래스에서 구현하려고하는 '뒤집기'동작을 매우 잘 수행 할 수 있습니다.

+0

아주 좋은! +1 ...이 "받아 들여지는"희망! –

+0

오 이런, 정말 고마워요! –

2

귀하의 시나리오에 맞게 UniformGrid을 권하고 싶습니다. 빠른 검색은 도움이 될만한 코드와 스크린 샷이 포함 된 this article을 산출했습니다.

+0

UniformGrid의 가장 중요한 부분은 ItemsControl의 ItemsPanel을 사용하도록 설정하는 것입니다. 그런 다음 ItemsSorce를 통해 카드를 바인딩 할 수 있으며 XAML에서 각 카드를 선언 할 필요가 없습니다. – rmoore

+0

나는 XAML에 정적 카드 수 대신에 얼마나 많은 카드를 가지고 놀고 싶었는지 물어 보았다. ItemsControl/ItemSource에 대한 기사가 있습니까? –

+0

@rmoore를 말할 수는 없지만 그는 UniformGrid를 ListBox의 ItemsPanel로 사용하는 것에 대해 이야기하고 있습니다. 다음은 WrapPanel과 유사한 작업을 수행하는 기사입니다. http://compilewith.net/2008/03/wpf-listbox-itemspaneltemplate-and.html –

0

WPF에 테이블이 있습니다. 시작하기에 좋은 article입니다. 경험에 비추어 볼 때 WPF의 표는 사용하기 쉽지 않으며 일반적으로 그리드를 사용하는 것이 더 좋습니다.

+1

Table 개체는 TextBlocks 및 FlowDocuments에서 사용되며 많은 UI 요소가 아닙니다. – YotaXP

관련 문제