Mengapa (Style)Application.Current.Resources[FrameBorder] tidak mengizinkan saya mengakses sumber daya di ResourceDirectory saya

Saya membuat sumber daya di file FrameRes.xaml seperti ini:

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms" 
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
                    x:Class="Japanese.Resources.FrameRes">
    <Style x:Key="FrameBorder" TargetType="Frame">
        <Setter Property="CornerRadius" Value="2" />
        <Setter Property="HasShadow" Value="false" />
        <Setter Property="Margin" Value="10,0" />
        <Setter Property="BorderColor" Value="{DynamicResource LineColor}" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="VerticalOptions" Value="Start" />
    </Style>
</ResourceDictionary>

dan ini terkandung di dalamnya:

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:converters="clr-namespace:Japanese" 
             xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="Japanese.App">
    <Application.Resources>
        <ResourceDictionary Source="/Resources/FooterRes.xaml" />
        <ResourceDictionary Source="/Resources/FrameRes.xaml" />
    </Application.Resources>
</Application>

Ketika saya mencoba mengakses ini di C# seperti ini maka gagal dan mengatakan tidak ada referensi ke FrameBorder:

var fb2 = (Style)Application.Current.Resources["FrameBorder"];

Ketika saya mencoba mengakses ini di C# seperti ini, ini berhasil:

Application.Current.Resources.TryGetValue("FrameBorder", out object frameBorder);
var fb = (Style)frameBorder;

Adakah yang tahu mengapa cara pertama tidak berhasil. Bagiku itu terlihat sama.


person Alan2    schedule 24.11.2018    source sumber
comment
Saya menghadapi masalah ini dan saya memposting solusinya di sini: stackoverflow.com/a/67992365/6846888   -  person Ângelo Polotto    schedule 15.06.2021


Jawaban (2)


Cara Anda mengaturnya, Anda memiliki ResourceDictionary di dalam ResourceDictionary lain tanpa kunci/nama/referensi. Saat Anda memanggil Application.Current.Resources["FrameBorder"];, Anda mengakses level paling atas dari kamus dan mencari "FrameBorder", bukan sub-levelnya. Namun, panggilan TryGetValue melewati semua level Kamus.

Baca Dokumen untuk memahami cara mengakses nilai dari Kamus.


Oke, jadi saya telah bermain-main dengan tag dan file ResourceDictionary, dan saya dapat melihat di mana kesalahan Anda.

Menurut Xamarin Forms Docs di ResourceDictionary, Anda dapat menambahkan file ResourceDictionary XAML yang berdiri sendiri ke App.xaml Anda seperti:

<App ...>
    <App.Resources>

            <!-- Add more resources here -->

            <ResourceDictionary Source="MyResourceDictionary.xaml" />

            <!-- Add more resources here -->

    </App.Resources>
    ...
</App>

Anda dapat mengganti App dengan ContentPage atau ContentView, tergantung penggunaan Anda.

Apa fungsinya?

Sederhananya, ini akan membuat objek ResourceDictionary baru dan menggabungkan file ResourceDictionary lainnya ke dalamnya. Mari kita bahas lebih detail.

Mari kita mulai dengan melihat properti Application.Current.Resources, yang bertipe ResourceDictionary dan mengimplementasikan ICollection, IDictionary, dan IResourceDictionary. Mengingat antarmuka yang diimplementasikannya, Anda dapat memperoleh nilai berdasarkan ID numerik atau string (misal: App.Current.Resources[0] atau App.Current.Resources["LabelStyle"]). Ini mengakses konten kamus tingkat atas, jadi hanya konten yang telah dibuat dalam tag <[App/ContentPage/ContentView].Resources>.

Anda juga memiliki properti bernama MergedDictionaries, yang mengimplementasikan ICollection. Artinya Anda hanya dapat mengakses item daftar berdasarkan ID numerik (misal: MyMergedDictionary[0]).

Saat Anda menambahkan file ResourceDictionary seperti:

<ResourceDictionary Source="MyResourceDictionary.xaml" />

Anda sebenarnya menggabungkan file ini dengan file ResourceDictionary saat ini. Untuk kemudian mengakses konten MyResourceDictionary Anda akan memanggil (dalam C#):

App.Current.Resources.MergedDictionaries[0]["InternalKeyName"]

Ini mungkin lebih baik dijelaskan seperti ini:

<App ...>
    <App.Resources>

            <!-- Called using App.Current.Resources["PrimaryColor"] -->
            <Color x:Key="PrimaryColor">#2196F3</Color>

            <!-- Called using App.Current.Resources.MergedDictionaries[0]["InternalKeyName"] -->
            <ResourceDictionary Source="MyResourceDictionary.xaml" />

    </App.Resources>
    ...
</App>

Kasus Anda

Dalam kasus Anda, Anda memiliki dua kamus yang digabungkan ke dalam Sumber Daya Aplikasi Anda: FooterRes dan FrameRes.

Untuk manajemen yang lebih baik, saya akan membuat enum seperti:

public enum MergedResourcesEnum
{
    Footer,
    Frame
}

dan gunakan enum ini saat memanggil sumber daya di C# seperti:

Application
    .Current
    .Resources
    .MergedDictionaries[(int)MergedResourcesEnum.Frame]["FrameBorder"];
person Tom    schedule 26.11.2018
comment
Saya memeriksa dokumen tetapi saya masih tidak yakin bagaimana cara mengakses nilai dari dalam file yang saya gabungkan ke dalam direktori sumber daya saya. Perhatikan bahwa sejak saya memposting pertanyaan, saya mencoba menghapus ResourceDirectory terluar seperti yang Anda sarankan tetapi masih tidak berhasil. - person Alan2; 29.11.2018
comment
Oke, saya telah membuka dokumen Xamarin Forms, dan saya telah mengubah jawaban saya dengan menambahkan sedikit informasi lebih lanjut. - person Tom; 29.11.2018
comment
Ini seharusnya merupakan jawaban yang diterima. Saya seorang insinyur dukungan MSFT Xamarin. - person jgoldberger - MSFT; 01.12.2018

Anda dapat mencoba menghapus tag ResourceDictionary bagian luar dan keduanya

var fb2 = (Style)Application.Current.Resources["FrameBorder"];

Dan

Application.Current.Resources.TryGetValue("FrameBorder", out object frameBorder);
var fb = (Style)frameBorder;

bekerja dengan benar.

Jadi kode xaml Anda seperti ini:

(Harap abaikan nama paket dan FooterRes.xaml yang tidak terkait karena saya tidak membagikan file FooterRes.xaml Anda)

<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App75.App">
    <Application.Resources>
        <ResourceDictionary Source="/Resources/FooterRes.xaml" />
    </Application.Resources>
</Application>
person AbbyWang - MSFT    schedule 28.11.2018
comment
Saya telah mencoba melakukan ini dan masih tidak dapat menemukan sumber dayanya - person Alan2; 29.11.2018
comment
@ Alan2 Karena saya tidak memiliki kode lengkapnya, saya baru saja membuat demo sederhana dan berfungsi dengan baik menggunakan solusi saya. Bisakah Anda membagikan proyek Anda agar saya lebih mudah menyelesaikan masalah ini. - person AbbyWang - MSFT; 29.11.2018