Avatar billede kongen72 Nybegynder
28. januar 2011 - 07:41 Der er 18 kommentarer og
1 løsning

MVC - Visning af først bogstav

Hej

Hvordan får jeg vist det første bogstav i et ord?

har f..eks følgende i min tabel:

Avis
Banan
Kiwi

vil have dem listet som:

A - B - K

Har været ude i nederstående kode, men det virker ikk.. hvorfor ??

var list = db.Indretning.Where(x => x.Navn.Substring(0,1).StartsWith("A")).ToList();

            return View(list);


tak på forhånd ;-)
Avatar billede platik Nybegynder
28. januar 2011 - 18:22 #1
Where er nok ikke den rigtige at bruge. Vælger jo en del af din liste.

Tror dette virker.

var list = db.Indretning.Select(x => x.Navn.First());
Avatar billede janus_007 Nybegynder
28. januar 2011 - 20:26 #2
Ja platik havde næsten ret.

Det skal skrives som

return db.Indretning.Select(x => x.Navn.Substring(0,1));

.First returnerer det første element fra en sekvens og da navn er en property vil x.Navn.First() ikke kunnne lade sig gøre :)
Avatar billede kongen72 Nybegynder
28. januar 2011 - 20:53 #3
Hej janus_007

Får følgende fejl når jeg debugger:

The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery`1[System.String]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcProject1.Models.Indretning]'.

hvordan får jeg den af vejen ?

Tak på forhånd ;-)
Avatar billede johny Nybegynder
29. januar 2011 - 01:48 #4
@janus_007: Han havde skam ret. String er en IEnumerable<char>, så det eneste problem var at han returnerede en IEnumerable<char>, og det er næppe det OP skal bruge.

@kongen72: Din View metode, hvad tager den imod, samt hvad gør den? For det som både janus og platik nævner henter det ud du skal bruge, men hvordan forsøger du at vise det?
Avatar billede kongen72 Nybegynder
30. januar 2011 - 21:21 #5
Hej johny!

Sådan ser mit view ud.

Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcProject1.Models.Indretning>>"

    <table>

    <% foreach (var item in Model) { %>
   
        <tr>
            <td>
                <%: item.Navn %>
            </td>
        </tr>
   
    <% } %>

    </table>
Avatar billede johny Nybegynder
31. januar 2011 - 08:08 #6
Nu er jeg ikke nogen ørn til MVC, men læste lige lidt op på det.

Det du forsøger at gøre her, er at hente noget ud fra en klasse, allerede inden du giver klassen til dit view, og det er et problem, fordi din view klasse forventer at få en "MvcProject1.Models.Indretning" klasse, hvilket du også kan se på "Inherits" delen af dit view.

Tag istedet for at lave en tynd klasse som den her f.eks.

public class IndretningView{
  public string Navn {get;set;}
  public char Forbogstav {get;set}
}

Den kan du så i stedet bruge i dit view, ved at lave en inherits på den i stedet, for så vil din code behind komme til at se sådan her ud:

return db.Indretning.Select(e => new IndretningView{ Navn = e.Navn, Forbogstav = e.Navn.First() });

Kan det ikke gøre det?
Avatar billede johny Nybegynder
31. januar 2011 - 08:08 #7
Og ja, så skal du selvfølgelig bare bruge item.Forbogstav i stedet for item.Navn
Avatar billede kongen72 Nybegynder
31. januar 2011 - 15:49 #8
Hej

Får samme fejl som før: The model item passed into the dictionary is of type 'MvcProject1.ViewModels.IndretningViewModel', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcProject1.ViewModels.IndretningViewModel]'.

Sådan ser min kode ud nu:

view model

    public class IndretningViewModel
    {
        public List<string> forbogstav { get; set; }
    }

controller
        public ViewResult Index()
        {
            var list = db.Indretning.Select(x => x.Navn.Substring(0,1));

            var ViewModel = new ViewModels.IndretningViewModel
            {
                forbogstav = list.ToList()
            };

            return View(ViewModel);
}

view

Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcProject1.ViewModels.IndretningViewModel>>"
    <table>

    <% foreach (var item in Model) { %>
   
        <tr>
            <td>
                <%: item.forbogstav %>
            </td>
        </tr>
   
    <% } %>

    </table>


Kan du se problemet ??
Avatar billede johny Nybegynder
31. januar 2011 - 19:13 #9
Ja, du er nød til at bruge view klassen (IndretningView) som den jeg skrev til dig. Om du vil bibeholde navn property'en eller ej, er så op til dig. Det er så denne du smider i View. Er som sagt ikke så skarp i MVC, men så må syntaxen så blive sådan her:

return View(db.Indretning.Select(e => new IndretningView{ Navn = e.Navn, Forbogstav = e.Navn.First() }));
Avatar billede janus_007 Nybegynder
31. januar 2011 - 23:19 #10
Hvis du har en liste og gerne vil have første bogstav fra hver item, så skal du skrive som jeg har gjort...

return db.Indretning.Select(x => x.Navn.Substring(0,1));

Forudsat at din indretning indeholder en property / field navngivet Navn!

Det med Navn.First() vil ikke virke, da Navn ikke er en sekvens. Jeg ved ikke hvorfor johny bliver ved at påstå det?

forudsat:
Avis
Banan
Kiwi

Så vil :
return View(db.Indretning.Select(e => new IndretningView{ Navn = e.Navn, Forbogstav = e.Navn.First() }));

Du få en liste som ser ud på flg. måde:
Avis, Avis
Banan, Avis
Kiwi, Avis

Og det er jo ikke det du vil!!

Årsagen til du får denne:
The model item passed into the dictionary is of type 'System.Data.Objects.ObjectQuery`1[System.String]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcProject1.Models.Indretning]'.

Er fordi at return db.Indretning.Select(x => x.Navn.Substring(0,1));, netop returnerer en liste a strings (nøjagtigt som du bad om ;-)), men fejlen fortæller også tydeligt at den forventer en model af typen IEnumerable<Indretning>

Nummer 2 fejl du skriver:
Får samme fejl som før: The model item passed into the dictionary is of type 'MvcProject1.ViewModels.IndretningViewModel', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcProject1.ViewModels.IndretningViewModel]'.

Fortæller at du nu er mere på rigtigt spor, nu skal du bare have stadig have IEnumerable<Indretning>, istedet for IndretningViewModel.

Jeg anbefaler at du bare går tilbage til din Indretning, den er nemlig fin nok, der er ingen grund til at opfinde nye klasser.
Så du skal bare returnere IEnumerable<Indretning>...

altså:

var list = db.Indretning.ToList();
return View(list);

Den siger også du kan nøjes med en IEnumerable, List implementerer IEnumerable, så ovenstående vil virke fint, men du kan altså også blot sige:
return db.Indretning;

Anyway...
Når det så er gjort og det at du vil have et bogstav er tydeligvis en præsentation og således intet med forretningslogik at gøre, så skal du gøre det direkte i dit view, altså:

Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcProject1.ViewModels.Indretning>>"
    <table>

    <% foreach (var item in Model) { %>
 
        <tr>
            <td>
                <%: item.Substring(0,1) %>
            </td>
        </tr>
 
    <% } %>

    </table>
Avatar billede johny Nybegynder
01. februar 2011 - 00:34 #11
Janus, tag nu lige at teste det selv så, eller slå det op? :)

"A string is a sequential collection of Unicode characters, typically used to represent text, while a String is a sequential collection of System.Char objects that represents a string."

Men ja, din løsning er umiddelbart pænere, selvom jeg godt kan lide view klasser da de er nemmere at styre. Og igen, det er sådan set korrekt den løsning jeg kommer med, jeg lægger bare styringen i code behind, af gammel vane, fordi det så er lettere at genbruge forretningslogik. Jeg har så ikke nogen anelse om hvordan koden skal bruges, og der fungerer det helt udmærket med dit eksempel. :)
Avatar billede janus_007 Nybegynder
01. februar 2011 - 00:57 #12
Nope johny... du er galt på den ;-) First() gør præcis som jeg skriver.

Og jep... definitionen.
"A string is a sequential collection of Unicode characters, typically used to represent text, while a String is a sequential collection of System.Char objects that represents a string."

Men men årsagen er... string implementerer bare ikke IEnumerable og derfor kan kan ikke behandles som du gerne vil :) dvs. linq extensionen findes ikke på string.


Jeg er 100% klar over hvad din tanke er med codebehind, men MVC kræver at vi ændrer vores opfattelse en anelse når det kommer til præsentation.


PS: Og genbrug af 1. bogstav hmm ;-)  (ejj.. ved godt hvad du mener)

Hent evt. Linqpad og efterprøv, nu har vi snart brugt tid nok på denne diskussion.
Avatar billede kongen72 Nybegynder
01. februar 2011 - 03:02 #13
tak janus_007 det hjalp :-) -svar ?
Avatar billede kongen72 Nybegynder
01. februar 2011 - 04:10 #14
lige en sidste ting. hvad skal der til for at få bogstavet til at vises kun 1 gang?

som f.eks:

A
Ananas
Agurk
B
Banan
Brød.. osv..
Avatar billede janus_007 Nybegynder
02. februar 2011 - 00:16 #15
Det er faktisk lidt sværere... nu ved jeg ikke lige hvor meget du skal bruge af Model, men du kan umiddelbart løse det på 2 måder:

<% foreach (var item in Model.Substring(0,1).Distinct()) { %>

        <tr>
            <td>
                <%: item %>
            </td>
        </tr>

    <% } %>

eller:

return db.Indretning.Select(x => new Indretning(){Navn = x.Navn.Substring(0,1).Distinct());

Skal du bruge din TR til andet? eller er det kun en liste af begyndelsesbogstaver?
Avatar billede janus_007 Nybegynder
02. februar 2011 - 00:54 #16
Tak til johny for at have korrigeret mig mht. til om String implementerer IEnumerable, det gør den! Jeg ved ikke lige hvad jeg tænkte på da jeg skrev det hehe....

Anyway... den vil nu stadig kun give det første bogstav fra første element og der ønskes første bogstav fra hvert element.

Beklager misinformationen her :-|
Avatar billede kongen72 Nybegynder
02. februar 2011 - 01:40 #17
tak igen har fået det hele til at virke perfekt, så det er super:-). smider du et svar, så vi kan afslutte denne tråd?
Avatar billede janus_007 Nybegynder
03. februar 2011 - 17:06 #18
Super
Avatar billede johny Nybegynder
03. februar 2011 - 17:33 #19
Nu ved jeg ikke helt hvad det var for en løsning du forsøgte at nå frem til, men du kunne evt. prøve med den her, så tror jeg den opfylder alle kravene du har til det.

<% foreach (var item in Model.Select(e => e.Substring(0,1)).Distinct()) { %>

        <tr>
            <td>
                <%: item %>
            </td>
        </tr>

<% foreach (var itemInner in Model.Where(e => e.Substring(0,1) == item) { %>

  <tr>
    <td>
                <%: itemInner %>
            </td>
        </tr>

    <% } %>

<% } %>
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester