简体   繁体   English

设置填充数据绑定的单个XAML项的样式

[英]Style A Single XAML Item That Is Populated With Data Binding

I have a C# ObservableCollection<> that is populating a XAML <ListBox> where each item uses <DataTemplate> . 我有一个C# ObservableCollection<> ,它正在填充XAML <ListBox> ,其中每个项目都使用<DataTemplate> Said list is just a list of date/content pairs where one of the pairs is today's (whatever day you might look at it) date. 所述列表仅仅是日期/内容对的列表,其中一对是今天(无论您看什么日子)的日期。 What I would like to do is give "today's" pair a little "sizzle" (technically, just set .Foreground = (Brush)Resources["PhoneAccentBrush"]; ). 我想做的是给“今天的”对增加一些“嘶嘶声”(从技术上讲,只需设置.Foreground = (Brush)Resources["PhoneAccentBrush"]; )。

Now, if you notice the /* using ObservableCollection<> chunks, I already accomplished what I was desiring by Insert() . 现在,如果您注意到/* using ObservableCollection<>块的/* using ObservableCollection<> ,我已经完成了Insert()想要的操作。 I'm simply wanting to do the same thing, using <DataTemplate> , as it seems like a more appropriate way of coding. 我只是想使用<DataTemplate>做同样的事情,因为这似乎是一种更合适的编码方式。

BTW...The only reasons I included the level of code verbosity is that someone would, invariably, ask for more code and the comments might help someone out (I know I've been, greatly, helped by code comments from others). 顺便说一句...我把代码详细程度包括在内的唯一原因是,人们总是会要求更多的代码,而注释可能会帮助某人(我知道,我得到了他人的代码注释的帮助很大)。

XAML: XAML:

<ListBox x:Name="readingschedule" ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock FontSize="20" TextWrapping="Wrap" FontWeight="SemiBold" Text="{Binding Date}"/>
                <TextBlock FontSize="27" TextWrapping="Wrap" Margin="0, 0, 0, 20" Text="{Binding Chapter}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<!-- replacing with data template
<StackPanel x:Name="readingschedule"/>
-->

C#: C#:

public MainPage()
{
    InitializeComponent();

    // get daily bible reading json results
    dailyBibleReading();

    // data binding for reading schedule
    readingschedule.DataContext = collection_readingschedule;

    // data binding for today's chapter
    todayschapter.DataContext = collection_todayschapter;
}

// create a collection (like an array) for the binding data to be added to
public ObservableCollection<ReadingSchedule> collection_readingschedule = new ObservableCollection<ReadingSchedule>();
// class to define the parts of the collection
public class ReadingSchedule
{
    public ReadingSchedule() { }
    public ReadingSchedule(string date, string chapter)
    {
        Date = date;
        Chapter = chapter;
    }
    public string Date { get; set; }
    public string Chapter { get; set; }
}

// create a collection (like an array) for the binding data to be added to
public ObservableCollection<TodaysChapter> collection_todayschapter = new ObservableCollection<TodaysChapter>();
// class to define the parts of the collection
public class TodaysChapter
{
    public TodaysChapter() { }
    public TodaysChapter(string reference, string text)
    {
        Reference = reference;
        Text = text;
    }
    public string Reference { get; set; }
    public string Text { get; set; }
}

// json connecting and processing example (http://nkishorchandra.blogspot.in/2012/10/parsing-json-in-windows-phone.html)
public void dailyBibleReading()
{
    // the the daily bible reading information for the whole week surrounding today
    DateTime today = DateTime.Today;
    // define default variables
    DateTime begindate = DateTime.Today.AddDays(-7);
    DateTime enddate = DateTime.Today.AddDays(7);
    DayOfWeek day = today.DayOfWeek;
    // redefine variables
    if (day == DayOfWeek.Sunday)
    {
        begindate = DateTime.Today.AddDays(-6);
        enddate = DateTime.Today.AddDays(5);
    }
    if (day == DayOfWeek.Monday)
    {
        begindate = DateTime.Today;
        enddate = DateTime.Today.AddDays(4);
    }
    if (day == DayOfWeek.Tuesday)
    {
        begindate = DateTime.Today.AddDays(-1);
        enddate = DateTime.Today.AddDays(3);
    }
    if (day == DayOfWeek.Wednesday)
    {
        begindate = DateTime.Today.AddDays(-2);
        enddate = DateTime.Today.AddDays(2);
    }
    if (day == DayOfWeek.Thursday)
    {
        begindate = DateTime.Today.AddDays(-3);
        enddate = DateTime.Today.AddDays(1);
    }
    if (day == DayOfWeek.Friday)
    {
        begindate = DateTime.Today.AddDays(-4);
        enddate = DateTime.Today;
    }
    if (day == DayOfWeek.Saturday)
    {
        begindate = DateTime.Today.AddDays(-5);
        enddate = DateTime.Today.AddDays(6);
    }
    string url = "http://www.flcbranson.org/api/dailybiblereading?begindate=" + begindate + "&enddate=" + enddate;

    WebClient dailyBibleReading = new WebClient();
    dailyBibleReading.DownloadStringCompleted += new DownloadStringCompletedEventHandler(dailyBibleReading_DownloadStringCompleted);
    dailyBibleReading.DownloadStringAsync(new Uri(url));
}
void dailyBibleReading_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    // do something with the feed here
    //string data = e.Result;
    //MessageBox.Show(data);
    // using Json.NET to deserialize the JSON content (http://json.codeplex.com/)
    // don't forget to include "using Newtonsoft.Json;" at the top
    // <RootObject> is the name of a class
    var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);

    // used to specify insert position of textblocks (below)
    int schedule_position = 0;
    int fontsize = 27;
    foreach (var chapter in rootObject.dailychapter)
    {
        //MessageBox.Show(chapter.date);
        //MessageBox.Show(chapter.verses[0].text);

        // reading schedule
        // great examples of working with dates (http://www.dotnetperls.com/datetime)
        string chapter_date = chapter.date;
        // Friday, November 3, 2013
        string chapter_date_readable = DateTime.Parse(chapter_date).ToString("D");
        string chapter_book = chapter.book;
        int chapter_chapter = chapter.chapter;
        string chapter_reference = chapter_book + " " + chapter_chapter;
        //MessageBox.Show("The chapter for " + chapter_date_readable + " is " + chapter_reference + ".");

        // Add items to the collection.
        collection_readingschedule.Add(new ReadingSchedule(chapter_date_readable, chapter_reference));

        /* using ObservableCollections<>
        // create new textblocks for each verse (requires an x:Name element to already be present in xaml)
        TextBlock schedule_date = new TextBlock();
        // textblock properties (http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontsize(v=vs.110).aspx)
        schedule_date.Text = chapter_date_readable;
        // font weight names (http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.fontweights(v=vs.105).aspx)
        schedule_date.FontWeight = FontWeights.SemiBold;
        schedule_date.TextWrapping = TextWrapping.Wrap;
        schedule_date.FontSize = fontsize * 0.75;
        // readingschedule is the x:Name that is already present in xaml
        readingschedule.Children.Insert(schedule_position, schedule_date);
        // increment the position
        schedule_position++;

        // create new textblocks for each verse (requires an x:Name element to already be present in xaml)
        TextBlock schedule_reference = new TextBlock();
        // textblock properties (http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontsize(v=vs.110).aspx)
        schedule_reference.Text = chapter_reference;
        schedule_reference.TextWrapping = TextWrapping.Wrap;
        schedule_reference.FontSize = fontsize;
        schedule_reference.Margin = new Thickness(0, 0, 0, fontsize * 0.75);
        // readingschedule is the x:Name that is already present in xaml
        readingschedule.Children.Insert(schedule_position, schedule_reference);
        // increment the position
        schedule_position++;
        */

        // today's chapter
        // 2013-11-03
        string iso8601 = DateTime.Today.ToString("yyyy-MM-dd");
        if (chapter.date == iso8601) {
            /*
            // give today's chapter reference a little pizzaz
            schedule_date.Foreground = (Brush)Resources["PhoneAccentBrush"];
            schedule_reference.Foreground = (Brush)Resources["PhoneAccentBrush"];
            */

            // used to specify insert position of textblocks (below)
            int verse_position = 0;
            foreach (var verse in chapter.verses)
            {
                //MessageBox.Show(verse.text);
                int number = verse.number;
                string text = verse.text;

                // Add items to the collection.
                collection_todayschapter.Add(new TodaysChapter(chapter_reference + ":" + number, text));

                /* using ObservableCollection<>
                // create new textblocks for each verse (requires an x:Name element to already be present in xaml)
                TextBlock verse_reference = new TextBlock();
                // textblock properties (http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontsize(v=vs.110).aspx)
                verse_reference.Text = chapter_reference + ":" + number;
                // font weight names (http://msdn.microsoft.com/en-us/library/windowsphone/develop/system.windows.fontweights(v=vs.105).aspx)
                verse_reference.FontWeight = FontWeights.SemiBold;
                verse_reference.TextWrapping = TextWrapping.Wrap;
                verse_reference.FontSize = fontsize * 0.75;
                // todayschapter is the x:Name that is already present in xaml
                todayschapter.Children.Insert(verse_position, verse_reference);
                // increment the position
                verse_position++;

                // create new textblocks for each verse (requires an x:Name element to already be present in xaml)
                TextBlock verse_text = new TextBlock();
                // textblock properties (http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.fontsize(v=vs.110).aspx)
                verse_text.Text = text;
                verse_text.TextWrapping = TextWrapping.Wrap;
                verse_text.FontSize = fontsize;
                verse_text.LineHeight = fontsize * 1.25;
                verse_text.Margin = new Thickness(0, 0, 0, fontsize * 0.75);
                // todayschapter is the x:Name that is already present in xaml
                todayschapter.Children.Insert(verse_position, verse_text);
                // increment the position
                verse_position++;
                */
            }
        }
    }
}

// classess for the daily bible reading api json result
// classes generated by json2csharp (http://json2csharp.com)
// generated class names were a little odd so I made them more appropriate
public class Verses
{
    public int number { get; set; }
    public string text { get; set; }
}
public class DailyChapter
{
    public string date { get; set; }
    public string book { get; set; }
    public int chapter { get; set; }
    public List<Verses> verses { get; set; }
}
public class RootObject
{
    public List<DailyChapter> dailychapter { get; set; }
}

Also, if you see something that it just stupid, feel free to point out better ways of doing things. 另外,如果您发现某些东西只是愚蠢的,请随时指出更好的做事方法。 I am very new to C# and XAML. 我对C#和XAML非常陌生。 I'm sure that there are better ways of doing what I'm doing. 我敢肯定,有更好的方式来做我正在做的事情。 I just don't know them. 我只是不认识他们。 A lot of it is just hacking away at example code and stuff. 其中很多只是破解示例代码和东西。

Edit... 编辑...

Another thread says that DataTemplate.Triggers isn't supported on Windows Phone. 另一个线程说Windows Phone不支持DataTemplate.Triggers Is there another way? 还有另一种方法吗?

You can use a DataTrigger : 您可以使用DataTrigger

<DataTemplate>
    <StackPanel x:Name="sp">
        <TextBlock FontSize="20" TextWrapping="Wrap" FontWeight="SemiBold" Text="{Binding Date}"/>
        <TextBlock FontSize="27" TextWrapping="Wrap" Margin="0, 0, 0, 20" Text="{Binding Chapter}"/>
    </StackPanel>

    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Date.Date}" Value="{x:Static sys:DateTime.Today}">
            <Setter TargetName="sp" Property="Background" Value="Red" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

To make your view models more generic, I would recommend having a Boolean property IsToday in the ReadingSchedule class. 为了使视图模型更通用,我建议在ReadingSchedule类中具有一个布尔属性IsToday So, your ReadingSchedule class would look like this: 因此,您的ReadingSchedule类将如下所示:

public class ReadingSchedule
{
    public ReadingSchedule() { }
    public ReadingSchedule(string date, string chapter)
    {
        Date = date;
        Chapter = chapter;
    }

private bool _isToday;
public bool IsToday
{
    get { return _isToday; }
    private set { _isToday = value; }
}

private string _date;
public string Date 
{
    get { return _date; }
    set
    {
        if (Convert.ToDateTime(value).Day == DateTime.Now.Day)
            IsToday = true;
        _date = value;
    }
}

public string Chapter { get; set; }
}

The change to your view is then as simple as checking for the IsToday value being true with a DataTrigger 你的看法的变化是那么作为检查的简单IsToday值是trueDataTrigger

<DataTemplate>
    <StackPanel x:Name="sp">
        <TextBlock FontSize="20" TextWrapping="Wrap" FontWeight="SemiBold" Text="{Binding Date}"/>
        <TextBlock FontSize="27" TextWrapping="Wrap" Margin="0, 0, 0, 20" Text="{Binding Chapter}"/>
    </StackPanel>

    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsToday}" Value="true">
            <Setter TargetName="sp" Property="Background" Value="Red" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

I think it's probably better to doit this way than to compare dates in the view, which is less concerned with logic. 我认为这样做比在视图中比较日期要好,因为后者不关心逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM