ListBox, Zapisywanie i odczytywanie stanu

0

Witam serdecznie. Tworzę aplikację do sklepu windows 8.1.

<ListBox x:Name="listBox1" Height="475" Canvas.Left="10" Canvas.Top="229" Width="580" Background="White" BorderBrush="{x:Null}" SelectionChanged="listBox1_SelectionChanged" Loaded="listBox1_Loaded" Unloaded="listBox1_Unloaded">
                <ListBox.ItemTemplate>
                    <DataTemplate >
                        <StackPanel x:Name="Panel" Orientation="Horizontal" Width="505" Height="130" VerticalAlignment="Top" ToolTipService.ToolTip="{Binding Note}">
                            <Border Height="60" Width="60" Margin="10,10,0,10">
                                <Image Source="{Binding Image}" Stretch="UniformToFill" Margin="0" Height="50" Width="50"/>
                            </Border>
                            <StackPanel x:Name="Panel1" Orientation="Vertical" VerticalAlignment="Center" Margin="0,0,0,0" HorizontalAlignment="Center">
                                <TextBlock x:Name="textboxName" Text="{Binding Name}" Margin="10,0,0,0" Width="100" Height="50" TextTrimming="WordEllipsis" FontSize="22"/>
                            </StackPanel>
                            <StackPanel x:Name="Panel2" Orientation="Vertical" VerticalAlignment="Center" Margin="0,0,0,0" HorizontalAlignment="Center">
                                <TextBlock x:Name="textboxKW" Text="{Binding KW}" Margin="10,0,0,0" Width="100" Height="50" TextTrimming="WordEllipsis" FontSize="22" Foreground="Red" />
                            </StackPanel>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
public class DataSource
    {
        
        public string Name { get; set; }
        public string Image { get; set; }
        public string Note { get; set; }
        public string KW { get; set; }
        public string RO { get; set; }

        public DataSource(string _Name, string _Image, string _Note, string _KW, string _RO)
        {            
            Name = _Name;
            Image = _Image;
            Note = _Note;
            KW = _KW;
            RO = _RO;
        }
    }        
}

Chciałbym muc zapisać stan listBoxa1 np. do pliku tekstowego. a dokładniej wartości KW, Name, Note.

Kiedyś stworzyłem taką metodę do zapisu:

class File
    {
        public File() { }

        public async Task Delete(string deletePath)

        {
            bool fileExists1;

            string DeletePath = deletePath;

            StorageFolder local = ApplicationData.Current.LocalFolder;

            try // Sprawdzanie czy pliki istnieją:
            {
                StorageFile _File1Check = local.GetFileAsync(DeletePath).AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
                fileExists1 = _File1Check != null;

            }
            catch
            {
                fileExists1 = false;
            }

            if (fileExists1 == false) //Jeżeli nie istnieje tworzymy plik
            {

                byte[] fileBytes1 = System.Text.Encoding.UTF8.GetBytes("0".ToCharArray());

                var file1 = await local.CreateFileAsync(DeletePath,
                CreationCollisionOption.ReplaceExisting);

                using (var s = await file1.OpenStreamForWriteAsync())
                {
                    s.Write(fileBytes1, 0, fileBytes1.Length);
                }
            }
            else //Jeżeli istnieje usuwamy
            {
                var _File1 = await local.GetFileAsync(DeletePath);

                await _File1.DeleteAsync(StorageDeleteOption.PermanentDelete);
            }
        }
        public async Task<string> Load(string loadPath)
        {
            string LoadPath = loadPath;
            bool fileExists1;


            StorageFolder local = ApplicationData.Current.LocalFolder;

            try // Sprawdzanie czy pliki istnieją:
            {
                StorageFile _File1Check = local.GetFileAsync(LoadPath).AsTask().ConfigureAwait(false).GetAwaiter().GetResult();
                fileExists1 = _File1Check != null;

            }
            catch
            {
                fileExists1 = false;
            }

            if (fileExists1 == false) //Jeżeli nie istnieje tworzymy plik
            {

                byte[] fileBytes1 = System.Text.Encoding.UTF8.GetBytes("0".ToCharArray());

                var file1 = await local.CreateFileAsync(LoadPath,
                CreationCollisionOption.ReplaceExisting);

                using (var s = await file1.OpenStreamForWriteAsync())
                {
                    s.Write(fileBytes1, 0, fileBytes1.Length);

                    return null;
                }
            }
            else //Jeżeli istnieje odczytujemy
            {
                var _File18 = await local.OpenStreamForReadAsync(LoadPath);

                using (StreamReader streamReader1 = new StreamReader(_File18))
                {
                    string Save = streamReader1.ReadToEnd();

                    return Save;
                }
            }
        }
        public async Task Save(string savePath, string save)
        {
            string SavePath = savePath;
            string Save = save;

            StorageFolder local = ApplicationData.Current.LocalFolder;

            byte[] fileBytes = Encoding.UTF8.GetBytes(Save.ToCharArray());

            var file = await local.CreateFileAsync(SavePath,
                CreationCollisionOption.ReplaceExisting);

            using (var s = await file.OpenStreamForWriteAsync())
            {
                s.Write(fileBytes, 0, fileBytes.Length);
            }
        }       
    }
}

Czy istnieje możliwość wykorzystania jej do zapisu, oraz odczytu stanu listBoxa1?

0

Tak.

0

Mógłbyś mnie naprowadzić?

            var dataSource = listBox1.SelectedItem as DataSource;
            var SAVE = dataSource.KW.ToString();
            var Saveing = new File();
            await Saveing.Save("SAVE.txt", SAVE);

Próbowałem coś takiego do zapisu wartości KW ale działa to w przypadku zapisu pojedynczej pozycji listBox1. Jak rozpisać to żeby zapisywało mi wszystkie wartości w np. jednym pliku, odczytywało w nowym zdarzeniu i dodawało do ListBox.?

0

Udało mi się zrobić coś takiego:

         private async void appBarButton_Save_Click(object sender, RoutedEventArgs e)
        {           
            ListBoxItem items = null;
            for (var i = 0; i < listBox1.Items.Count; i++)
            {
                items =  listBox1.Items[i] as ListBoxItem;
                
                    var dataSource = listBox1.SelectedItem as DataSource;
                    var kw = dataSource.KW.ToString();
                    var name = dataSource.Name.ToString();
                    var note = dataSource.Note.ToString();
                    
                    string item = string.Format("{0} | {1}| {2}", name, kw, note);
                    var Saveing = new File();
                    await Saveing.Save("Save.txt", item);                                    
            }
        }

Teraz problem w tym że chciałbym zapisać kilka pozycji listboxa do nowej linii w tym samym pliku Save.txt. Prosiłbym o pomoc :)

1

Z takim zapisem to się nie da.

var file = await local.CreateFileAsync(SavePath,
                CreationCollisionOption.ReplaceExisting);

Przecież w każdym kroku pętli tworzysz zupełnie nowy plik :/
To trzeba rozwiązać zupełnie inaczej. W ogóle mam wrażenie, że strasznie nakombinowałeś w tym kodzie.

Możliwości masz kilka.
Najprościej, żebyś nie grzebał w kodzie, to zebrać wszystko co chcesz zapisać do jakiejś listy stringów, a potem tą listę zapisać do pliku. Np:

List<string> output = new List<string>();
foreach(var item in listBox.SelectedItems)
{
  DataSource ds = (DataSource)item;
  output.Add(ds.ToString());
}

File.WriteAllLines(output);

To jest bardziej pseudokod, ale wiesz o co chodzi.

2

Chcesz zapisywać tylko wartości KW, Name i Note? A czemu nie wszystkie, nie będzie prościej?

Bo jeśli wszystkie, to zrób sobie serializację. Doinstaluj do projektu paczkę Newtonsoft.Json i masz wtedy:

var itemsString = JsonConvert.SerializeObject(listBox1.Items)

I to ci zbuduje listę twoich obiektów typu DataSource, w postaci stringa, którego możesz za jednym zamachem zapisać: FileIO.WriteTextAsync(file, saved);.

Z kolei do odczytania możesz pójść w drugą stronę:

var saved = await FileIO.ReadTextAsync(file);
var loaded = JsonConvert.DeserializeObject<IEnumerable<DataSource>>(saved);
foreach (var item in loaded)
{
    listBox.Items.Add(item);
}

(gdzie file to oczywiście odwołanie do IStorageFile stworzonego albo otwartego przez CreateFileAsync)


Jeżeli z jakichś powodów chcesz to zrobić ręcznie, to możesz na przykład wykorzystać takie funkcje:

private string SaveItemsToString()
{
    StringBuilder sb = new StringBuilder();
    foreach (DataSource item in listBox.Items)
    {
        sb.AppendLine($"{item.Name}|{item.Note}|{item.KW}");
    }

    return sb.ToString();
}

private async void SaveData(string path, string data)
{
    StorageFolder local = ApplicationData.Current.LocalFolder;
    var file = await local.CreateFileAsync(path, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, data);
}

private void LoadStringToItems(string data)
{
    string[] lines = data.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
    foreach (var item in lines)
    {
        var i = item.Split('|');
        listBox.Items.Add(new DataSource { Name = i[0], Note = i[1], KW = float.Parse(i[2]) });
    }
}

private async Task<string> LoadData(string path, string data)
{
    StorageFolder local = ApplicationData.Current.LocalFolder;
    var file = await local.GetFileAsync(path);
    return await FileIO.ReadTextAsync(file);
}

Ale trzeba będzie na przykład uważać, żeby w Name albo Note nigdy nie było znaku |, bo to zepsuje parsowanie wyniku.

0

Zastosowałem się do twoich rad Ktos:

         private async void listBox1_Loaded(object sender, RoutedEventArgs e)
        { 
             StorageFolder local = ApplicationData.Current.LocalFolder;
             var newFile = await local.GetFileAsync("Save.txt");
             var saved = await FileIO.ReadTextAsync(newFile);
             var loaded = JsonConvert.DeserializeObject<IEnumerable<DataSource>>(saved);
             foreach (var item in loaded)
             {
                listBox1.Items.Add(item);
             }

        }
        private async void listBox1_Unloaded(object sender, RoutedEventArgs e)
        {
            var saved = JsonConvert.SerializeObject(listBox1.Items);
            StorageFolder local = ApplicationData.Current.LocalFolder;
            StorageFile newFile = await local.CreateFileAsync("Save.txt", CreationCollisionOption.ReplaceExisting);
            await FileIO.WriteTextAsync(newFile, saved);
        }  
     ```

A teraz sprawa wygląda tak. Gdybyś mi nie pomógł pewnie nie wpadłbym nigdy na pomysł użycia Jsona. Mam nikłą wiedzę o programowaniu i po prostu nie widziałem jak do tego podejść. Dzięki wam mogę nauczyć się czegoś nowego. Dziękuję wszystkim serdecznie za pomoc :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1