【问题标题】:Setting an image for an ImageCell in ListView on Xamarin Forms在 Xamarin 表单的 ListView 中为 ImageCell 设置图像
【发布时间】:2021-07-19 01:07:13
【问题描述】:

我正在尝试使用 ListView 在 Xamarin Forms 上创建一个项目。在我的 ListView 里面我有一个 ImageCell。当项目正在运行时,它只显示 ImageCell 的文本。我需要它来显示文本、细节和图像。我已经编写了我认为正确的代码,但我不知道为什么它不起作用。我的图像在我的资源文件夹中,并且我正确标记了它们。这个项目的重点是创建一个事件日历。用户将创建一个事件,选择事件的日期和时间,保存它,它应该显示事件发生的星期几的图片,文本部分中的事件名称,以及详细信息部分中事件的日期和时间。有人可以看看我的代码,看看我做错了什么吗? 这是我的MainPage.XAML

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MorganHall_CE04.MainPage">

    <StackLayout>
        <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
            <Label Text="Code Example 4" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
        </Frame>
        <ListView x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                <ImageCell x:Name="imageCell" Text="" Detail="" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Button x:Name="addButton" Text="ADD EVENT" HorizontalOptions="End" />
    </StackLayout>
</ContentPage>

这是我的MainPage.XAML.CS 很多...:

    {
        private List<TaskData> taskList = new List<TaskData>();

        public MainPage()
        {
            InitializeComponent();

            addButton.Clicked += AddButton_Clicked;
            
            DataTemplate events = new DataTemplate(typeof(ImageCell));
            events.SetBinding(ImageCell.TextProperty, new Binding("Text"));
            events.SetBinding(ImageCell.DetailProperty, new Binding("Date" + "Time"));
            //SetValue to change color properties
            events.SetValue(ImageCell.TextColorProperty, Color.DarkBlue);
            events.SetValue(ImageCell.DetailColorProperty, Color.DarkMagenta);
            //SetImages ex: saveButton.ImageSource = ImageSource.FromFile("save48.png");
            string image = SetImages();
            events.SetValue(ImageCell.ImageSourceProperty, ImageSource.FromFile(image));
             

            listView.ItemTemplate = events;
            

            //Ask the listView to let us know anytime an item gets selected
            listView.ItemSelected += ListView_ItemSelected;

            MessagingCenter.Subscribe<string>(this, "ModifiedMessage", (sender) =>
            {
                this.ReloadListData();
                Debug.WriteLine(sender);
            });

            //Reload saved list items when app is opened
            this.ReloadListData();
        }

        private string SetImages()
        {
            //set string variable to hold the image source
            string picture = "";
            string day = "";
            //Check if taskList is empty
            if (taskList != null)
            {
                //loop through task list
                for (int i = 0; i < taskList.Count; i++)
                {
                    DateTime date = taskList[i].Date;
                    day = date.ToString("dddd");
                }
                
                //set images to the day of the week using a switch statement
                switch (day)
                {
                    case "Sunday":
                        picture = "sunday.png";
                        break;
                    case "Monday":
                        picture = "monday.png";
                        break;
                    case "Tuesday":
                        picture = "tuesday.png";
                        break;
                    case "Wednesday":
                        picture = "wednesday.png";
                        break;
                    case "Thursday":
                        picture = "thursday.png";
                        break;
                    case "Friday":
                        picture = "friday.png";
                        break;
                    case "Saturday":
                        picture = "saturday.png";
                        break;
                }
            }

            return picture;
        }

        private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            //Push taskEntry page with what was selected
            //Double check if what was selected is valid
            if (e.SelectedItem != null)
            {
                Navigation.PushAsync(new TaskEntryPage());
                MessagingCenter.Send<TaskData>((TaskData)e.SelectedItem, "EditItemMessage");
            }

        }

        protected override void OnAppearing()
        {
            //Leave base.OnApperearing
            base.OnAppearing();

            
        }

        private void ReloadListData()
        {
            //Tell taskList to clear
            taskList.Clear();

            //loop through all files that were generated and add to task list and set to data source for listView
            // * means "anything as long as it matches the last half of file name
            var files = Directory.EnumerateFiles(App.FolderPath, "*.CE04.txt");
            foreach (var filename in files)
            {
                //Read information from file
                using (var reader = new StreamReader(filename))
                {
                    var data = File.ReadAllLines(filename);
                    //Convert the date string to a DateTime object
                    DateTime dt = DateTime.Parse(data[1]);
                    //Convert the time string to a TimeSpan object
                    TimeSpan time = TimeSpan.Parse(data[2]);

                    //Add data to the taskList
                    taskList.Add(new TaskData
                    {
                        Filename = filename,
                        Text = data[0],
                        Date = dt,
                        Time = time

                    });
                }
            }
            listView.ItemsSource = taskList.OrderBy(d => d.Date).ToList();
        }

        private void AddButton_Clicked(object sender, EventArgs e)
        {
            Navigation.PushAsync(new TaskEntryPage
            {
                BindingContext = new TaskData()
            });
        }

这是我的TaskEntryPage.XAML.cs,应该保存信息,它只保存看起来像的文本:

    {
        TaskData editTask;

        public TaskEntryPage()
        {
            InitializeComponent();

            //Set pictures for 

            saveButton.ImageSource = ImageSource.FromFile("save48.png");
            deleteButton.ImageSource = ImageSource.FromFile("delete48.png");

            saveButton.Clicked += OnSaveButton_Clicked;

            deleteButton.Clicked += DeleteButton_Clicked;

            //subscribe to message from MainPage
            MessagingCenter.Subscribe<TaskData>(this, "EditItemMessage", (sender) =>
            {
                editTask = sender;
                taskEntry.Text = editTask.Text;
                datePicker.Date = editTask.Date;
                timePicker.Time = editTask.Time;
            });
        }

        protected override void OnAppearing()
        {
            //Leave base.OnAppearing
            base.OnAppearing();
        }

        async private void DeleteButton_Clicked(object sender, EventArgs e)
        {
            bool answer = await DisplayAlert("DELETE EVENT", "Are you sure you want to delete this event? This cannot be undone.", "YES", "NO");
            if (answer)
            {
                if (editTask != null)
                {
                    //Check if file already exists
                    if (File.Exists(editTask.Filename))
                    {
                        //Delete file
                        File.Delete(editTask.Filename);
                    }
                }

                MessagingCenter.Send<string>("ModifiedMessage Called from Delete", "ModifiedMessage");

                await Navigation.PopAsync();
            } 
        }

        private void OnSaveButton_Clicked(object sender, EventArgs e)
        {
            string filename = Path.Combine(App.FolderPath, $"{Path.GetRandomFileName()}.CE04.txt");
            string messageType = "New";
            messageType = "Edit";
            var binding = BindingContext as TaskData;
            binding.Date = datePicker.Date;
            binding.Time = timePicker.Time;
            //I can't figure out another way besides StreamWriter
            using (var writer = new StreamWriter(filename))
            {
                //write data to file
                writer.WriteLine(taskEntry.Text);
                writer.WriteLine(datePicker.Date);
                writer.WriteLine(timePicker.Time);
            }

            MessagingCenter.Send<string>("ModifiedMessage Called from " + messageType, "ModifiedMessage");

            Navigation.PopAsync();
        }
    }

最后同样重要的是,我的TaskData.cs 保存了文件名、日期和时间:

    {
        public string Filename { get; set; }
        public string Text { get; set; }
        public DateTime Date { get; set; }
        public TimeSpan Time { get; set; }
    }

我知道这很多,但我非常感谢您的帮助!

【问题讨论】:

  • 哪里有很多错误。首先,您为什么要在 XAML 和代码中创建模板?选择其中一个(通常首选 XAML)。第二,Binding("Date" + "Time") 不会做你想做的事。在 XAML 中执行此操作并使用 FormatString 会简单得多。第三,SetImages() 没有做任何有用的事情。您可以通过使用IValueConverterDate 转换为用作图像源的字符串来大大简化此操作。

标签: c# android xamarin xamarin.forms


【解决方案1】:

正如 Jason 所说,您的代码中有几个问题。

我已经根据您的代码实现了这个功能,并且可以正常工作。可以参考以下代码:

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:converters="clr-namespace:ImageCellApp.converters"
             x:Class="ImageCellApp.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <converters:DateToStringConverter x:Key="dateToStringConverter"/>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
            <Label Text="Code Example 4" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
        </Frame>
        <ListView x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ImageCell x:Name="imageCell" Text="{Binding Text}" ImageSource="{ Binding Date, Converter={StaticResource dateToStringConverter}}" >
                        <ImageCell.Detail>
                            <MultiBinding StringFormat="{}{0} {1}">
                                <Binding Path="Date" />
                                <Binding Path="Time" />
                            </MultiBinding>
                        </ImageCell.Detail>

                    </ImageCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Button x:Name="addButton" Text="ADD EVENT" HorizontalOptions="End" />
    </StackLayout>

</ContentPage>

MainPage.xaml.cs

public partial class MainPage : ContentPage
{
    private List<TaskData> taskList = new List<TaskData>();
    public MainPage()
    {
        InitializeComponent();

        this.ReloadListData();
    }

    private void ReloadListData()
    {
        //Tell taskList to clear
        taskList.Clear();

        taskList.Add(new TaskData { Filename = "fileName1", Text = "text1", Date = new DateTime(2021,7,19) , Time= new TimeSpan(1,20,30) });
        taskList.Add(new TaskData { Filename = "fileName2", Text = "text2", Date = new DateTime(2021, 7, 18), Time = new TimeSpan(2, 10, 30) });
        taskList.Add(new TaskData { Filename = "fileName3", Text = "text3", Date = new DateTime(2021, 7, 16), Time = new TimeSpan(1, 9, 30) });
        taskList.Add(new TaskData { Filename = "fileName4", Text = "text4", Date = new DateTime(2021, 7, 16), Time = new TimeSpan(1, 8, 30) });
        taskList.Add(new TaskData { Filename = "fileName5", Text = "text5", Date = new DateTime(2021, 7, 15), Time = new TimeSpan(1, 7, 30) });
        taskList.Add(new TaskData { Filename = "fileName6", Text = "text6", Date = new DateTime(2021, 7, 12), Time = new TimeSpan(1, 6, 30) });

        listView.ItemsSource = taskList;
    }
}

班级DateToStringConverter.cs

public class DateToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        DateTime date = (DateTime)value;

        string picture = "";
        string day = "";
        day = date.ToString("dddd");

        System.Diagnostics.Debug.WriteLine("------------> day = " + day);

        //set images to the day of the week using a switch statement
        switch (day)
        {
            case "Sunday":
                picture = "sunday.png";
                break;
            case "Monday":
                picture = "monday.png";
                break;
            case "Tuesday":
                picture = "tuesday.png";
                break;
            case "Wednesday":
                picture = "wednesday.png";
                break;
            case "Thursday":
                picture = "thursday.png";
                break;
            case "Friday":
                picture = "friday.png";
                break;
            case "Saturday":
                picture = "saturday.png";
                break;
        }
        return picture;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

结果是:

注意:

1.你把XAML和你的页面代码搞混了,我们一般更喜欢用XAML来实现我们的页面;

2.如果要将多个字段绑定到一个视图,可以使用MultiBinding来实现,可以使用如下代码:

                        <ImageCell.Detail>
                        <MultiBinding StringFormat="{}{0} {1}">
                            <Binding Path="Date" />
                            <Binding Path="Time" />
                        </MultiBinding>
                    </ImageCell.Detail>

3.如果要根据字段 public DateTime Date { get; set; }显示图片,可以使用IValueConverter来实现。

public class DateToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        DateTime date = (DateTime)value;

        string picture = "";
        string day = "";
        day = date.ToString("dddd");

        System.Diagnostics.Debug.WriteLine("------------> day = " + day);

        //set images to the day of the week using a switch statement
        switch (day)
        {
            case "Sunday":
                picture = "sunday.png";
                break;
            case "Monday":
                picture = "monday.png";
                break;
            case "Tuesday":
                picture = "tuesday.png";
                break;
            case "Wednesday":
                picture = "wednesday.png";
                break;
            case "Thursday":
                picture = "thursday.png";
                break;
            case "Friday":
                picture = "friday.png";
                break;
            case "Saturday":
                picture = "saturday.png";
                break;
        }
        return picture;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

【讨论】:

  • 哇,这太棒了!谢谢!我不知道 multiBinding,我非常感谢您将其分解并为我重新创建它。看到它肯定会帮助我更好地学习它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2014-09-26
  • 1970-01-01
相关资源
最近更新 更多