开发者

data doesn't show on Text={Binding}?

Im quite new to silverlight and windows 7 phone development. And I'm not sure what I missed but apparantly I missed something because it's not working as intended.

My goal, is to show a list of creatures, with only their name and hitpoints. But the whole Text={Binding}-stuff apparently doesn't work. So I wonder if any of you guys could help me with this.

When i say it dosen't work, its because the data is in the creature list, but not in the page/textblocks - it shows the right amount of creatures, but just not the data.

XAML

<phone:PhoneApplicationPage 
x:Class="RPG_Assistent.Pages.DamageTrackerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
    </StackPanel>

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <!--<Button Content="Damage" Height="72" HorizontalAlignment="Left" Margin="0,618,0,0" Name="btnDamage" VerticalAlignment="Top" Width="160" Click="btnDamage_Click" />
        <TextBox Height="72" HorizontalAlignment="Left" Margin="158,618,0,0" Name="txtDamage" Text="" VerticalAlignment="Top" Width="286" KeyUp="NumericOnlyTextBox_KeyUp"></TextBox>-->
        <ListBox ItemsSource="{Binding creatureList}" Height="500" HorizontalAlignment="Center" Margin="6,6,0,0" Name="listBox1" VerticalAlignment="Top" Width="400">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Button Width="400" Height="120" >
                        <Button.ContentTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" Height="80" Width="200">
                                    <StackPanel Orientation="Vertica开发者_如何学Pythonl" Height="40">
                                        <TextBlock Width="100" FontSize="22" Text="Name:" Height="40"/>
                                        <TextBlock Width="100" Text="{Binding Name}" Height="40"/>
                                    </StackPanel>
                                    <StackPanel Orientation="Vertical" Height="40">
                                        <TextBlock Width="100" FontSize="22" Text="Hitpoints:" Height="40"/>
                                        <TextBlock Width="100" Text="{Binding HitPoints}" Height="40"/>
                                    </StackPanel>
                                </StackPanel>
                            </DataTemplate>
                        </Button.ContentTemplate>
                    </Button>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Grid>

<!--Sample code showing usage of ApplicationBar-->
<!--<phone:PhoneApplicationPage.ApplicationBar>
    <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
        <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
        <shell:ApplicationBar.MenuItems>
            <shell:ApplicationBarMenuItem Text="MenuItem 1"/>
            <shell:ApplicationBarMenuItem Text="MenuItem 2"/>
        </shell:ApplicationBar.MenuItems>
    </shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>-->

CS - called when page is done loading stuff in. ( called after InitializeComponent(); on my DamageTracker Page )

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
namespace RPG_Assistent.Pages
{
    public partial class DamageTrackerPage : PhoneApplicationPage
    {
        List<Models.Creature> creatureList { get; set; }

        public DamageTrackerPage()
        {
            InitializeComponent();
            creatureList = new List<Models.Creature>();


            #region ApplicationTitle Setup
            ApplicationTitle.Text = Constants.AppName;
            ApplicationTitle.TextAlignment = Constants.AppName_TextAlignment;
            ApplicationTitle.FontSize = Constants.AppName_FontSize;
            ApplicationTitle.FontWeight = Constants.AppName_FontWeight;
            #endregion

           //SetInputScope(txtDamage);


            LoadCreatures();
            DataContext = this;
        }

        public void LoadCreatures()
        {


            string name;

            for (int i = 0; i < 10; i++)
            {
                name = "Monster " + i + 1;
                creatureList.Add(new Models.Creature(name));

            }

        }

        public void btnDamage_Click(object sender, RoutedEventArgs e)
        {

        }

        #region textbox control - makes numeric only
        private void SetInputScope(TextBox textBoxControl)
        {
            InputScopeNameValue digitsInputNameValue = InputScopeNameValue.TelephoneNumber;
            textBoxControl.InputScope = new InputScope()
            {
                Names = {
                    new InputScopeName()
                    {
                        NameValue = digitsInputNameValue
                    }
                }
            };
        }

        private void MaskNumericInput(TextBox textBoxControl)
        {
            string[] invalidCharacters = { "*", "#", ",", "(", ")", "x", "-", "+", " ", "@", "." };

            for (int i = 0; i < invalidCharacters.Length; i++)
            {
                textBoxControl.SelectionStart = textBoxControl.Text.Length;
            }
        }

        private void NumericOnlyTextBox_KeyUp(object sender, KeyEventArgs e)
        {
            MaskNumericInput((TextBox)sender);
        }
        #endregion


    }
}

CS - Creature class, is placed in "Models" folder - because i thought i would be clever

using System;

using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace RPG_Assistent.Models
{
    public class Creature
    {
        public string Name { get; set; }
        public int HitPoints { get; set; }
        public string Type { get; set; }

        public Creature(string name)
        {
            this.Name = name;
            this.HitPoints = 0;
            this.Type = "Images/mob.jpg";

        }
        public void Damage(int damage)
        {
            HitPoints += damage;
        }
        public void Bloodied()
        {
            switch (this.Type)
            {
                case "Images/mob.jpg":
                    this.Type = "Images/mobhurt.jpg";
                    break;
                case "Images/mobhurt.jpg":
                    this.Type = "Images/mob.jpg";
                    break;
            }
        }

    }
}


Since you are binding to a list of Creatures, you do not need to put Creature.Name. You should be able to change it to Text={Binding Name} and Text={Binding Hitpoints}


It looks like it should be Text={Binding Name} or Text={Binding HitPoints}

EDIT: but, Text={Binding Path=Name} or Text={Binding Path=HitPoints} would work too.

EDIT 2: Sorry, I didn't notice your comment. I don't have VS in the computer, so I can't try it myself, but try setting the DataType on the DataTemplate to Creature.


Update your binding to the following. I´ve dropped Creature, from the binding path. Then it should work

<StackPanel Orientation="Vertical" Height="40">
  <TextBlock Width="100" FontSize="22" Text="Name:" Height="40"/>
  <TextBlock Width="100" Text="{Binding Path=Name}" Height="40"/>
</StackPanel>
<StackPanel Orientation="Vertical" Height="40">
   <TextBlock Width="100" FontSize="22" Text="Hitpoints:" Height="40"/>
   <TextBlock Width="100" Text="{Binding Path=HitPoints}" Height="40"/>
 </StackPanel>


You always bind to the DataContext with direct bindings, and when setting the ItemsSource to a list, the DataContext becomes each item in the list for each row it will represent. So your thinking here is completely correct!

However: ContentControl act the same. When you set the Content of a ContentControl you basicly override the DataContext for the Content. The DataContext is thus set as your StackPanel, and it will render itself as your StackPanel, but you will also try to Bind to your StackPanel, and not to your Creature object anymore.

So you might want to do this:

Move your content StackPanel to a DataTemplate, set this DataTemplate as ContentTemplate on your Button and set the Content of the Button to a Binding of your Creature object, like so:

<Button Width="400" Height="120" Content="{Binding}">
    <Button.ContentTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal" Height="80" Width="200">
            <StackPanel Orientation="Vertical" Height="40">
            <TextBlock Width="100" FontSize="22" Text="Name:" Height="40"/>
            <TextBlock Width="100" Text="{Binding Path=Name}" Height="40"/>
            </StackPanel>
            <StackPanel Orientation="Vertical" Height="40">
            <TextBlock Width="100" FontSize="22" Text="Hitpoints:" Height="40"/>
            <TextBlock Width="100" Text="{Binding Path=HitPoints}" Height="40"/>
            </StackPanel>
        </StackPanel>
    </DataTemplate>
    </Button.ContentTemplate>
</Button>


My preferred way of handling these occasions I set up a collection for the view. It would look something like this

public class CreatureList : ObservableCollection<Creature>
{
    // at least implement the constructor
}

After that you can use the new collection class in your window XAML definition.

<ResourceDictionary>
    <local:CreatureList x:Key="creatures" />
</ResourceDictionary>

The definition of the local namespace has to be set to the assembly namespace where the class CreatureList would be found. After that you can use the defined list in your listbox definition.

<ListBox Name="creatureListBox" ItemsSource="{Binding Source={StaticResource creatures}}">
    <!-- Template definition for each entry -->
</ListBox>

To use these objects in your window class, you have to set up some attributes and associate them to the specified entry.

public partial class DamageTrackerPage : PhoneApplicationPage
{
    private readonly CreatureList creatureList;
}

In the constructor of the class you bind the attribute to the specified XAML definition.

public DamageTrackerPage() {
    InitializeComponent();
    creatureList = FindResource("creatures") as CreatureList;
}

Now when you add entries to the list or remove entries from it the changes will be updated to your window automatically.

This is at least the way I'm doing it in WPF, but I'm sure for WinPhone apps that should be the same.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜