WPF

2009-06-05 6 views
7

में तालिका लेआउट मैं WPF के लिए बहुत नया हूं, इसलिए मैंने सिंटैक्स सीखने के लिए बस एक बहुत ही सरल मेमोरी कार्ड गेम बनाना शुरू कर दिया है। वह गेम है जहां सभी कार्ड नीचे आ रहे हैं, आप दो ओवर फ्लिप करते हैं और यदि वे मेल खाते हैं तो आप उन्हें हटा दें, अन्यथा उन्हें नीचे दोबारा हटाएं और फ्लिप की सबसे छोटी संख्या में सभी कार्ड को हटाने का प्रयास करें। जैसे मैंने कहा, बहुत सरल ... :)WPF

मेरा सवाल है, क्या HTML में कोई टेबल तत्व नहीं है, इसलिए मैं आसानी से मार्जिन के साथ गड़बड़ करने के बजाय कार्ड को एक समान लेआउट में डाल सकता हूं?

उत्तर

10

मैट हैमिल्टन के सुझाव के रूप में यूनिफॉर्मग्रिड का उपयोग करके इसका एक उदाहरण यहां दिया गया है।

सबसे पहले, कक्षाओं और डेटा को बनाने दें जो हम उपयोग करेंगे। प्रत्येक कार्ड एक कार्ड वस्तु द्वारा प्रतिनिधित्व किया जाएगा, और एक चेहरा संपत्ति है:

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

इसके बाद, हम एक वर्ग कार्ड के बारे में हमारी संग्रह है, और यह भी एक संपत्ति हमें कार्ड की संख्या निर्धारित करने देता हैं की आवश्यकता होगी । कार्डकॉलेक्शन के लिए हम ObservableCollection का उपयोग कर सकते हैं क्योंकि कार्ड को जोड़ा या निकाला जाने पर स्वचालित रूप से यूआई को सूचित किया जाएगा। यूआई को सूचित करने के लिए नंबरऑफकार्ड्स संपत्ति को अपनी स्वयं की विधि की आवश्यकता होगी, इसके लिए हम 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 का वर्गमूल हो जाएगा , और एक्सएएमएल में हमारे कार्ड वर्ग से जुड़ें। एक्सएएमएल के लिए मैंने एक साधारण आइटम कंट्रोल का उपयोग किया, ताकि यह चयन योग्य न हो, और मैंने डेटा टेम्पलेट को एक बटन बनने के लिए सेट किया है, ताकि प्रत्येक कार्ड पर क्लिक किया जा सके, यह सब कुछ आवश्यक है!

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 कार्यान्वयन है। चूंकि यह आपको 'फ़्लिपिंग' व्यवहार दे सकता है जिसे आप कार्ड क्लास में काफी अच्छी तरह कार्यान्वित करने की तलाश में हैं।

+0

बहुत अच्छा! +1 ... उम्मीद है कि यह "स्वीकार" हो जाता है! –

+0

ओह यह कमाल है, बहुत बहुत धन्यवाद! –

2

मैं आपके परिदृश्य के लिए UniformGrid की सिफारिश करता हूं। एक त्वरित खोज this article उत्पन्न हुई जिसमें कुछ कोड और स्क्रीनशॉट शामिल हैं जो मदद कर सकते हैं।

+0

यूनिफॉर्मग्रिड का सबसे अच्छा हिस्सा आइटम का नियंत्रण करने के लिए आइटम्सकंट्रोल के आइटम पैनेल सेट करने में सक्षम है। फिर कार्ड आइटमसॉर्स के माध्यम से बंधे जा सकते हैं और आपको XAML में प्रत्येक कार्ड घोषित करने की आवश्यकता नहीं है। – rmoore

+0

मैं उपयोगकर्ता से पूछने जा रहा था कि वे कितने कार्ड खेलना चाहते थे और फिर एक्सएएमएल में कार्ड की स्थिर संख्या रखने के बजाए उन्हें उत्पन्न करें। क्या आपके पास ContentControl/ItemSource के लिए कोई आलेख है? –

+0

मैं @rmoore के लिए बात नहीं कर सकता, लेकिन मैं इकट्ठा करता हूं कि वह एक वर्दीब्रिड का उपयोग सूची बॉक्स के लिए आइटमपैनल के रूप में करने के बारे में बात कर रहा है। यहां एक आलेख है जो रैपपैनेल के साथ कुछ ऐसा करता है: http://compilewith.net/2008/03/wpf-listbox-itemspaneltemplate-and.html –

0

डब्ल्यूपीएफ में एक टेबल है, इसके साथ शुरू करने पर यहां एक अच्छा article है। अनुभव से डब्ल्यूपीएफ में तालिका का उपयोग करना आसान नहीं है और ग्रिड का उपयोग करना आम तौर पर एक बेहतर विकल्प है।

+1

टेबल ऑब्जेक्ट का उपयोग टेक्स्टब्लॉक और फ्लो डॉक्यूमेंट्स में किया जाता है, और इतना यूआई तत्व नहीं। – YotaXP

संबंधित मुद्दे