Dziwny błąd z mojego convertera, odn. rzutowania na Mock

0

Mam dziwny błąd w swojej aplikacji, kompilator czepia się jakiegoś dziwnego rzutowania którego nie rozumiem skąd wziął:
treść wyjątku z okna "Lista Błędów" z Visual Studio 2019 (nie ma kodu błędu kompilatora):

Błąd		Nie można rzutować obiektu typu 'System.Collections.Generic.List'1[Mocks.WEzAP_WPF_Models_Programy_DaneProgramu_11_13218733]' na typ 'System.Collections.Generic.List'1[WEzAP_WPF.Models.Programy.DaneProgramu]'.	WEzAP_WPF	C:\Users\pawell\source\repos\WEzAP_Wydruk-Etykiet_v4.0\WEzAP_WPF\Views\WalidacjaProgramowUserControl.xaml	1

nie mam pojęcia skąd się wziął typ: Mocks.WEzAP_WPF_Models_Programy_DaneProgramu_11_13218733 - to musiał wygenerować gdzies VisualStudio?

StackTrace wskazuje na mój konwerter ListaProgramowToFlowDocumentConverter, gdy go zakomentuję w definicji <Control.Resources> (linia 17) to widok w projekcie wyświetla się poprawnie.
Powyższy błąd ma wpływ tylko na okno designera, gdy uruchomię program, program działa poprawnie, okno się wyświetla. Konwerter działa i wyświetla poprawnie tak jak ma wyświetlać nazwy programów z zakolorowanymi fragmentami tak jak ma wyświetlać.

Podgląd w oknie projektu:
Pytanie_podglądWidoku.PNG

Kod mojego konwertera:
(Generalnie chodzi o to aby w richTextBox wyświetlić obiekty typu DaneProgramu ale tak aby zaznaczone fragmenty nazwy danego programu były na żółtym tle)

public class ListaProgramowToFlowDocumentConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        List<DaneProgramu> listaNazwProgramow = (List<DaneProgramu>)value;
        FlowDocument fd = new FlowDocument();

        if (listaNazwProgramow!=null)
        {
            foreach (var item in listaNazwProgramow)
            {
                Paragraph paragraph = new Paragraph();

                string poczatek = item.SygnaturaSprzetu;
                string sygnaturaWersjiSoftu = item.SygnaturaWersjiSoftu;


                string odstep_Soft_Widok;
                string odstep_Widok_Revizja;
                string widok;
                if (item.DlugoscSygnaturyWersjiWidoku > 0)
                {
                    widok = item.SygnaturaWersjiWidoku;

                    int startIndex = item.IndexPozycjiWersjiSoftu + item.DlugoscSygnaturyWersjiSoftu;
                    int dlugoscSeparatora = item.IndexPozycjiWersjiWidoku - startIndex;
                    odstep_Soft_Widok = item.NazwaPlikuProgramu.Substring(startIndex, dlugoscSeparatora);

                    int startIndex2 = item.IndexPozycjiWersjiWidoku + item.DlugoscSygnaturyWersjiWidoku;
                    int dlugoscSeparatora2;

                    if (item.DlugoscSygnaturyRewizji > 0)
                        dlugoscSeparatora2 = item.IndexPozycjiRewizji - startIndex2;
                    else
                        dlugoscSeparatora2 = item.NazwaPlikuProgramu.Length - startIndex2;

                    odstep_Widok_Revizja = item.NazwaPlikuProgramu.Substring(startIndex2, dlugoscSeparatora2);
                }
                else
                {
                    odstep_Soft_Widok = "";
                    widok = "";

                    int start = item.IndexPozycjiWersjiSoftu + item.DlugoscSygnaturyWersjiSoftu;
                    int dlugosc;

                    if (item.DlugoscSygnaturyRewizji > 0)
                        dlugosc = item.IndexPozycjiRewizji - start;
                    else
                        dlugosc = item.NazwaPlikuProgramu.Length - start;

                    odstep_Widok_Revizja = item.NazwaPlikuProgramu.Substring(start, dlugosc);
                }

                string rewizja = item.SygnaturaRewizji;

                string resztaPoRewizji;
                if (item.DlugoscSygnaturyRewizji > 0)
                    resztaPoRewizji = item.NazwaPlikuProgramu.Substring(item.IndexPozycjiRewizji + item.DlugoscSygnaturyRewizji);
                else
                    resztaPoRewizji = "";



                paragraph.Inlines.Add(new Run(poczatek));
                paragraph.Inlines.Add(new Run(sygnaturaWersjiSoftu) { Background = Brushes.Yellow, FontWeight = FontWeights.Bold });
                paragraph.Inlines.Add(new Run(odstep_Soft_Widok));
                paragraph.Inlines.Add(new Run(widok) { Background = Brushes.Yellow, FontWeight = FontWeights.Bold });
                paragraph.Inlines.Add(new Run(odstep_Widok_Revizja));
                paragraph.Inlines.Add(new Run(rewizja) { Background = Brushes.Yellow, FontWeight = FontWeights.Bold });
                paragraph.Inlines.Add(new Run(resztaPoRewizji));


                fd.Blocks.Add(paragraph);
            }
        }

        return fd;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

kod mojej kontrolki RichTextbox'a do ktorego mozna bindować FlowDocument

public partial class BindowalnyRichTextBox : RichTextBox
{
    public BindowalnyRichTextBox()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty FlowDocumentProperty =
        DependencyProperty.Register(
            "BindowalnyDocument",
            typeof(FlowDocument), 
            typeof(BindowalnyRichTextBox),
            new FrameworkPropertyMetadata(
                null, new PropertyChangedCallback(OnDocumentChanged)));

    public new FlowDocument BindowalnyDocument
    {
        get { return (FlowDocument)GetValue(FlowDocumentProperty); }
        set { SetValue(FlowDocumentProperty, value); }
    }

    public static void OnDocumentChanged(DependencyObject obj, 
        DependencyPropertyChangedEventArgs args)
    {
        RichTextBox rtb = (RichTextBox)obj;
        rtb.Document = (FlowDocument)args.NewValue;
        //if (args.NewValue != null)
        //    rtb.Document = (FlowDocument)args.NewValue;
        //else
        //    rtb.Document = new FlowDocument();
    }
}

osadzenie kontrolki 'BindowalnyRichTextBox' na widoku wygląda tak:

<local:BindowalnyRichTextBox             Grid.Row="0" Grid.Column="2"
                                         Grid.ColumnSpan="2"
                                         Margin="3"
                                         IsReadOnly="True"
                                         BindowalnyDocument="{Binding ProgramyZZapisowUIDu, Converter={StaticResource ListaToFlowDoc}}">
    <local:BindowalnyRichTextBox.Resources>
        <Style TargetType="{x:Type Paragraph}">
            <Setter Property="Margin" Value="2"/>
        </Style>
    </local:BindowalnyRichTextBox.Resources>
</local:BindowalnyRichTextBox>
0

gdy zamiast komentować definicję konwertera w Usercontrol.Resources, zakomentuje całą metodę Convert w konwerterze to wszystko wraca do normy:

Coś jest nie tak z tymi liniami, ale nie rozumiem co

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            List<DaneProgramu> listaNazwProgramow = (List<DaneProgramu>)value;
            FlowDocument fd = new FlowDocument();
            
            //....
            ```
1

jak to przeważnie bywa, gdy spisuje się problem po to aby przedstawić go na forum, i aby dobrze go wytłumaczyć i pokazać co trzeba, wtedy znajduje się rozwiązanie:

Rozwiązaniem było najpierw zainicjowanie listy a dopiero potem przypisanie jej zrzutowanej wartości z parametru metody:

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            List<DaneProgramu> listaNazwProgramow = new List<DaneProgramu>();
            listaNazwProgramow = (List<DaneProgramu>)value;

            FlowDocument fd = new FlowDocument();
            //....
            ```
0

radość okazała się przedwczesna, nadal mam ten sam błąd :/ jeżeli ktoś wie o co chodzi to prośba o pomoc, ciężko się pracuje na widoku który "sztuczkami z za komentowaniem konwertera" trzeba sobie pokazywać. :/

3

sprawdź czy w ogóle value jest typu List<DaneProgramu> bo obstawiam, że na 99,9% nie jest. Nie masz też nigdzie w kodzie który podałeś podpiętego tego konwertera.

No i najważniejsze - exceptiona dałeś akurat tyle, że nie wiadomo o co mu chodzi - pogratulować...

1

Gdy występują dziwne błędy

  1. Zgaś visual studio
  2. Usuń wszystkie foldery bin i obj
  3. Odpal visual studio i zrekompiluj wszystko od zera

Zrób własne mocki które będziesz mógł kontrolować i podepnij pod d:BindowalnyDocument, masz przypisany jakiś d:DataContext w dokumencie? Pokaż cały XAML. Być może visual studio generuje własne mocki ale nic o tym nie wiem, w każdym razie wygenerowany gdzieś mock nie może być zamieniony w tej linii:

List<DaneProgramu> listaNazwProgramow = (List<DaneProgramu>)value;

możesz zrobić interfejs na DaneProgramu i rzutować na ten interfejs (wygenerowany gdzieś mock zapewne też będzie go implementować), albo po prostu używać as lub is i wyjść w tym momencie z konwertera jeśli typ się nie zgadza.

0

@abrakadaber: na screenie który załączyłem widać gdzie jest podpięty ten konwerter w widoku, linia 17 i 65.

Ciekawe jest to że pracując na Visual Studio 2022 Community nie mam tego problemu. A na drugim komputerze pracując na Visual Studio 2019 Profesional - problem jest :/

0

a czym jest ProgramyZmapowaneDobiezacegoIndeksu? BTW powinno być biezacego z małej?

1

problem masz tylko podczas designu - tzn. gdy visual próbuje pokazać jak wyglada kontrolka z bindowaniem (nie podczas uruchomienia aplikacji?)
https://stackoverflow.com/questions/1889966/what-approaches-are-available-to-dummy-design-time-data-in-wpf

0

niestety usuwanie katalogów bin i obj - nie pomogło :/

na tym problematycznym komputerze, jakiś czas temu usuwałem VisualStudio 2022 Community i zainstalowałem Visual Studio 2019 - może miec to związek?
Na komputerach na których nie mam tego problemu cały czas działam na VS 2022

1

Wbij się debugerem do wywalającej się linijki - tam, gdzie masz rzutowanie obiektu na listę, zobacz w okienkach debugera co przyszło, czy da się to rzutować. Jeśli zaś problem występuje tylko w trybie design, to wrzuć sobie te dane do jakiegoś pliku i ten plik podejrzyj.
Na pewno chodzi o to, że twój obiekt value ma typ, który nie daje się zrzutować na listę, kwestia tego co zrobić, żeby wszystko zadziałało, a do tego może przydać się informacja odnośnie typu value.
W najgorszym przypadku zrób value as List<DaneProgramu>.

BTW ten kod jest paskudny - spaghetti, mieszanie składni i języka polskiego z angielskim, nieprawidłowa składnia (C# to nie PHP).

2
ŁF napisał(a):

Jeśli zaś problem występuje tylko w trybie design, to wrzuć sobie te dane do jakiegoś pliku i ten plik podejrzyj.

Nie ma potrzeby zapisywać do pliku można debugować design time:

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