iT邦幫忙

1

如何在View上定義一個新的陣列,但來源是dynamic物件與List

正在嘗試自己練習MVC的View,在實作以下時有碰到問題,若我有一個dynamic物件(Option1),我想要在View上定義一個陣列,其內容組成是來自於這個dynamic物(Option1)以及自定義的List(rowStyle),請問我可以怎麼做呢?
想要的結果是:
新的陣列newOption1裡面包含
欄位Index放rowsIndex
欄位Name放rowsName
欄位Value : 判斷rowsIndex=rowStyleCompareIndexArray就放rowStyleFormatStyle的值

目前有嘗試自己撰寫,但是有錯誤,不知道可以怎麼調整呢?

程式如下:

@functions{
    public class RowStyle{
        public int[] CompareIndexArray{ get; set; }
        public string FormatStyle{ get; set; }
    }

    List<RowStyle> rowStyle = new List<RowStyle>()
    {
        new RowStyle {
            CompareIndexArray =  new int[] { 1 },
            FormatStyle = "title"
        },
        new RowStyle {
            CompareIndexArray =  new int[] { 2 },
            FormatStyle = "subTitle"
        },
        new RowStyle {
            CompareIndexArray =  new int[] { 3 },
            FormatStyle = "null"
        }
    };
}
@{
    var rows = ViewBag.Option1;
}

ViewBag.Option1的長相:
https://ithelp.ithome.com.tw/upload/images/20190901/20115336t6gcH7NP03.jpg

我寫了以下,但會跳出錯誤訊息

var newOption1 = rows.Select(x => new{
    option1.Index
    , option1.Name
    , Value = (rowStyle.CompareIndexArray.GetType().GetProperties())
        [x.Index=rowStyle.CompareIndexArray ? rowStyle.CompareIndexArray : "default"]
}).FirstOrDefault();

https://ithelp.ithome.com.tw/upload/images/20190901/20115336pvEw1lErnm.png

我寫了以下,但會跳出錯誤訊息,也不太知道要怎麼下判斷去放Value值

var newOption1 = from row in rows
   where row.Index=rowStyle.GetType("CompareIndexArray").GetProperties()
   select new { Index = row.Index, Name = row.Name, Value = rowStyle.FormatStyle }; 

https://ithelp.ithome.com.tw/upload/images/20190901/20115336etCB4awQqs.png

YoChen iT邦研究生 3 級 ‧ 2019-09-02 11:15:03 檢舉
良心建議妳還是先把Option1的類別建起來吧~XDDD
C#是強型別語言,既然是已知型別,就不要再用Dynamic了~
然後盡量多使用List少用Array,可以讓開發省事很多哦~
1
YoChen
iT邦研究生 3 級 ‧ 2019-09-02 11:40:24
最佳解答

建立一個新類別NewOption

public class NewOption{
    public int Index{ get; set; }
    public string Name{ get; set; }
    public string Value{ get; set; }
}

把資料整理進去NewOption的List

List<NewOption> newOptionList = new List<NewOption>();

foreach (var option in Option1.Options)
{
    NewOption newOption = new NewOption() {
        Index = option.Index,
        Name = option.Namr,
        Value = rowStyle.Where(style => style.CompareIndexArray.Contains(option.Index)).First().FormatStyle
    };
    newOptionList.Add(newOption);
}

然後開心使用newOptionList~XDDD

看更多先前的回應...收起先前的回應...
anniecat iT邦新手 3 級 ‧ 2019-09-02 13:44:39 檢舉

謝謝YoChen的幫忙,我使用這樣的方式後,有以下錯誤,不知道還可以怎麼調整呢?謝謝!!
https://ithelp.ithome.com.tw/upload/images/20190902/20115336GoVC8sQLR2.png

YoChen iT邦研究生 3 級 ‧ 2019-09-02 14:05:17 檢舉

使用泛型的方法要先

using System.Collections.Generic;
anniecat iT邦新手 3 級 ‧ 2019-09-02 14:19:40 檢舉

謝謝YoChen,引用以後,原本的錯誤仍然存在,後來有上網看相關引用,但錯誤還是存在...

YoChen iT邦研究生 3 級 ‧ 2019-09-02 15:09:49 檢舉

那就換個寫法吧~

Style = rowStyle.Where(x => Array.IndexOf(x.CompareIndexArray, option.Index) != -1).First().FormatStyle
    };
anniecat iT邦新手 3 級 ‧ 2019-09-02 16:00:50 檢舉

謝謝YoChen!目前成功了!

我有去看以下兩個用法(假設以String為例)

  • StringA.Contains(StringB):StringA裡面有無包含StringB
    這個看起來是List的用法

  • IndexOf(StringArray, String):判斷StringArray裡面有無包含String
    這個看起來是Array的用法

是因為我雖然建立的是List,但實際比較的東西是int[],所以要使用Array的方法嗎?

YoChen iT邦研究生 3 級 ‧ 2019-09-02 17:05:29 檢舉

您的理解沒錯,由於CompareIndexArray是Int[],所以用Array.IndexOf的方法是一定可行的~XDDD

另外有關Contains的部分,由於指定型別的Array本身可以實作IEnumerable,因此,照理來說Contains擴充功能應該要可以使用,我猜可能是使用Dynamic的關係,所以導致TSource對應不到型別,您可以試試看下方指定型別的方法,但不一定會成功,可以參考看看就好~XDDD

Style = rowStyle.Where(x => x.CompareIndexArray.Contains((int)option.Index), option.Index) != -1).First().FormatStyle
    };
anniecat iT邦新手 3 級 ‧ 2019-09-03 09:55:47 檢舉

昨天要回覆的時後已達上限XDD
有嘗試過是可行的,程式如下:

Style = rowStyle.Where(x => x.CompareIndexArray.Contains((int)option.Index)).First().FormatStyle

再次感謝您的幫忙!

1
小魚
iT邦大師 1 級 ‧ 2019-09-01 13:00:34

我沒看到你有定義ViewBag.Option1啊...

anniecat iT邦新手 3 級 ‧ 2019-09-02 10:22:13 檢舉

謝謝小魚的回覆,你說的定義是Option1原本的定義嗎?
還是指我要再另外做定義呢?

小魚 iT邦大師 1 級 ‧ 2019-09-02 10:43:51 檢舉
var newOption1

後面要再加一段

ViewBag.Option1 = newOption1;

不過我剛剛再看了一次你的問題,
好像你在這之前就卡住了...
不過沒有這一行執行出來也會有問題.
(雖然可以編譯)

anniecat iT邦新手 3 級 ‧ 2019-09-02 16:06:38 檢舉

謝謝小魚,後來解決這個問題了,很感謝你的幫忙!

2
舜~
iT邦高手 1 級 ‧ 2019-09-01 19:23:57

使用dynamic就無法使用Lambda/Linq

所以使用前要想辦法先轉型~~

Option1原本是什麼class?

比如說:您的Option1的類型是List< AA>
class AA{
int Index{get;set;}
string Name{get;set;}
}

因為透過ViewBag會變成dynamic類型,所以使用的時候要先轉型回來,這樣就可以使用Lambda/Linq了

var rows = (List< AA >) ViewBag.Option1;
或是
List< AA> rows = ViewBag.Option1;

看更多先前的回應...收起先前的回應...
anniecat iT邦新手 3 級 ‧ 2019-09-02 10:20:43 檢舉

謝謝舜~,不好意思還在學習寫程式,所以有很多都還在摸索,我的class:

public abstract partial class Subject {
    ...
    public static IEnumerable<Subject> FindInstances(String typeName) {
    ...
    }

請問這樣的話,要如何將透過ViewBag的dynamic類型做轉型呢?
還是,我想達到的目標不一定要使用Lambda/Linq呢?

這幾天有再找相關資料,有使用看看ExpandoObject,但它的結果不是我要的,也嘗試直接將var改成String但這樣的意義就不對了,不好意思在麻煩了 > <
轉成這樣也無法使用Lambda/Linq:
var rows = (Subject)ViewBag.Option1;

舜~ iT邦高手 1 級 ‧ 2019-09-02 10:36:16 檢舉

Lambda/Linq很方便,但只能用在強型別,不轉型的話就用一般迴圈處理吧~
轉型的話,我想您是多個Subject的陣列吧~~
var rows = (List< Subject>) ViewBag.Option1;//或Subject[]

anniecat iT邦新手 3 級 ‧ 2019-09-02 10:56:03 檢舉

舜~謝謝你,不過在執行時會跳出此錯誤訊息,不知道我還可以怎麼調整呢?
https://ithelp.ithome.com.tw/upload/images/20190902/20115336CMXFnEW7vg.jpg

舜~ iT邦高手 1 級 ‧ 2019-09-02 12:15:48 檢舉

看您的錯誤訊息,若改成這樣呢?
(Multiverse.Data.SubjectList< Subject>) ViewBag.Option1;

anniecat iT邦新手 3 級 ‧ 2019-09-02 13:48:51 檢舉

舜~謝謝你,目前還是會跳一樣的錯誤,看起來可能我要嘗試其他方法看看,真的很感謝你!!

舜~ iT邦高手 1 級 ‧ 2019-09-02 13:52:17 檢舉

我看太快,錯誤訊息是Multiverse.Data.SubjectList< Sentence >
您的類別確定是Subject不是Sentence?

舜~ iT邦高手 1 級 ‧ 2019-09-02 13:54:57 檢舉

或是您直接土法煉鋼,用foreach處理就不用管型別了

anniecat iT邦新手 3 級 ‧ 2019-09-02 14:01:45 檢舉

舜~不好意思,其實為了發問所以有將問題簡化,我的ViewBag.Option1存放的資料結構其實是樹狀的

anniecat iT邦新手 3 級 ‧ 2019-09-02 16:05:19 檢舉

舜~後來使用foreach解決這個問題,謝謝你讓我知道使用dynamic就無法使用Lambda/Linq,真的很感謝你的幫忙!

我要發表回答

立即登入回答