Sự khác biệt giữa StaticResource và DynamicResource trong WPF là gì?


474

Khi sử dụng các tài nguyên như cọ vẽ, mẫu và kiểu trong WPF, chúng có thể được chỉ định là Nguồn tĩnh

<Rectangle Fill="{StaticResource MyBrush}" />

hoặc dưới dạng DynamicResource

<ItemsControl ItemTemplate="{DynamicResource MyItemTemplate}"  />

Hầu hết thời gian (luôn luôn?), Chỉ có một hoạt động và lần khác sẽ ném ngoại lệ trong thời gian chạy. Nhưng tôi muốn biết tại sao:

  • Sự khác biệt chính là gì. Giống như bộ nhớ hoặc ý nghĩa hiệu suất
  • Có các quy tắc trong WPF như "bàn chải luôn tĩnh" và "mẫu luôn động", v.v.?

Tôi cho rằng sự lựa chọn giữa Tĩnh và Động không phải là tùy ý như có vẻ như ... nhưng tôi không thấy mô hình.


27
Điều quan trọng cần lưu ý là các nhà phát triển Ứng dụng Windows 8 không có DyanmicResource dưới dạng tùy chọn, chỉ có StaticResource.
Jerry Nixon

2
@Jerry Nixon Cảm ơn Chúa vì điều đó, tôi đã mất số lần tôi không thể làm gì được vì tôi đang sử dụng DynamicResource thay vì StaticResource hoặc ngược lại. Từ quan điểm lập trình viên, đây là sự phức tạp không cần thiết. Một sự tương tự là các định nghĩa khác nhau, tôi phải xác định rõ ràng liệu nó sống trên heap hay stack? Và nếu tôi hiểu sai nó sẽ ném một lỗi thời gian chạy thảm khốc?
Contango

Để được giải thích kỹ hơn về StaticResource và DynamicResource, và khi nào nên sử dụng từng loại, hãy xem msdn.microsoft.com/en-us/l Library / ms750613% 28v = vs.100% 29.aspx .
Michael Repucci

Câu trả lời:


466

Một StaticResource sẽ được giải quyết và gán cho thuộc tính trong quá trình tải XAML xảy ra trước khi ứng dụng thực sự chạy. Nó sẽ chỉ được chỉ định một lần và mọi thay đổi đối với từ điển tài nguyên bị bỏ qua.

Một DynamicResource gán một đối tượng Expression để tài sản trong quá trình tải nhưng không thực sự tra cứu tài nguyên cho đến khi thời gian chạy khi đối tượng Biểu hiện được hỏi về giá trị. Điều này trì hoãn việc tìm kiếm tài nguyên cho đến khi cần thiết trong thời gian chạy. Một ví dụ điển hình sẽ là một tham chiếu chuyển tiếp đến một tài nguyên được xác định sau này trong XAML. Một ví dụ khác là một tài nguyên thậm chí sẽ không tồn tại cho đến khi chạy. Nó sẽ cập nhật mục tiêu nếu từ điển tài nguyên nguồn được thay đổi.


4
Điều gì phải thay đổi trước khi tôi cần sử dụng DynamicResource? Lấy một ví dụ mẫu: tôi xác định nó một lần nhưng tất nhiên các trình kích hoạt và công cụ có thể thay đổi nội dung của mẫu nhưng mẫu vẫn giống nhau. StaticResource sẽ làm gì ở đây?
Isak Savo

5
Sử dụng StaticResource nếu tài nguyên bạn đang đính kèm được xác định trong XAML trước thời điểm sử dụng và sẽ không thay đổi trong suốt thời gian chạy ứng dụng. Trong trường hợp đó, bạn sẽ có hiệu suất tốt hơn với StaticResource.
Phil Wright

4
là haiWay ràng buộc áp dụng cho cả hai điều này, nếu có, sự khác biệt trong trường hợp đó là gì?
WhoIsNinja

11
Câu cuối cùng thực sự quan trọng:It will update the target if the source resource dictionary is changed.
MEMark 16/12/13

4
@IsakSavo Hãy xem xét một giao diện người dùng có chủ đề màu sắc, Với tài nguyên động, bạn có thể trao đổi một từ điển này sang một từ điển khác và mọi tài nguyên tham chiếu trong từ điển mới sẽ tự động cập nhật.
Gusdor

119

Tôi cũng bối rối về họ. Xem ví dụ này dưới đây:

<Window x:Class="WpfApplicationWPF.CommandsWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="CommandsWindow" Height="300" Width="300">

    <StackPanel>
        <Button Name="ButtonNew" 
                Click="ButtonNew_Click" 
                Background="{DynamicResource PinkBrush}">NEW</Button>
        <Image Name="ImageNew" 
               Source="pack://application:,,,/images/winter.jpg"></Image>
    </StackPanel>


    <Window.Background>
        <DynamicResource ResourceKey="PinkBrush"></DynamicResource>
    </Window.Background>

</Window>

Ở đây tôi đã sử dụng tài nguyên động cho nút và cửa sổ và chưa khai báo ở bất cứ đâu. Thời gian chạy nhanh, ResourceDipedia của hệ thống phân cấp sẽ được kiểm tra. Vì vậy, tôi chưa xác định nó, tôi đoán mặc định sẽ được sử dụng.

Nếu tôi thêm mã bên dưới để nhấp vào sự kiện của Nút, vì họ sử dụng DynamicResource, nền sẽ được cập nhật tương ứng.

private void ButtonNew_Click(object sender, RoutedEventArgs e)
{
    this.Resources.Add(  "PinkBrush"
                         ,new SolidColorBrush(SystemColors.DesktopColor)
                       );
}

Nếu họ đã sử dụng StaticResource:

  • Tài nguyên phải được khai báo trong XAML
  • Và đó cũng là "trước" chúng được sử dụng.

Hy vọng tôi xóa một số nhầm lẫn.


31

StaticResource sẽ được giải quyết khi xây dựng đối tượng.
DynamicResource sẽ được đánh giá và giải quyết mỗi khi kiểm soát cần tài nguyên.


21
  1. StaticResource sử dụng giá trị đầu tiên . DynamicResource sử dụng giá trị cuối cùng .
  2. DynamicResource có thể được sử dụng để tạo kiểu lồng nhau, StaticResource không thể.

Giả sử bạn có từ điển Kiểu lồng nhau này. LightGreen ở cấp độ gốc trong khi Pink được lồng bên trong Lưới.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="{x:Type Grid}">
        <Style.Resources>
            <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
                <Setter Property="Background" Value="Pink"/>
            </Style>
        </Style.Resources>
    </Style>
    <Style TargetType="{x:Type Button}" x:Key="ConflictButton">
        <Setter Property="Background" Value="LightGreen"/>
    </Style>
</ResourceDictionary>

Theo quan điểm:

<Window x:Class="WpfStyleDemo.ConflictingStyleWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ConflictingStyleWindow" Height="100" Width="100">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Styles/ConflictingStyle.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Button Style="{DynamicResource ConflictButton}" Content="Test"/>
    </Grid>
</Window>

StaticResource sẽ kết xuất nút dưới dạng LightGreen, giá trị đầu tiên được tìm thấy trong kiểu. DynamicResource sẽ ghi đè nút LightGreen thành Màu hồng khi hiển thị Lưới.

Nguồn tĩnh Nguồn tĩnh

Nguồn động Nguồn động

Hãy nhớ rằng VS Designer coi DynamicResource là StaticResource. Nó sẽ nhận được giá trị đầu tiên. Trong trường hợp này, VS Designer sẽ kết xuất nút dưới dạng LightGreen mặc dù thực tế nó có màu hồng.

StaticResource sẽ đưa ra lỗi khi loại kiểu cấp gốc (LightGreen) bị xóa.


13

Sự khác biệt chính là gì. Giống như bộ nhớ hoặc ý nghĩa hiệu suất

Sự khác biệt giữa tài nguyên tĩnh và động xuất hiện khi đối tượng cơ bản thay đổi. Nếu Brush của bạn được xác định trong bộ sưu tập Tài nguyên được truy cập theo mã và được đặt thành một đối tượng khác, Hình chữ nhật sẽ không phát hiện ra sự thay đổi này.

Tài nguyên tĩnh được truy xuất một lần bằng cách tham chiếu phần tử và được sử dụng cho vòng đời của tài nguyên. Trong khi đó, DynamicResource lấy lại mỗi khi chúng được sử dụng.

Nhược điểm của tài nguyên động là chúng có xu hướng làm giảm hiệu suất ứng dụng.

Có các quy tắc trong WPF như "bàn chải luôn tĩnh" và "mẫu luôn động", v.v.?

Cách thực hành tốt nhất là sử dụng Tài nguyên tĩnh trừ khi có một lý do cụ thể như bạn muốn thay đổi tài nguyên trong mã phía sau một cách linh hoạt. Một ví dụ khác về trường hợp bạn muốn sử dụng các phép nối lại động bao gồm khi bạn sử dụng SystemBrushes, SystenFonts và Tham số hệ thống.


7

Tìm thấy tất cả các câu trả lời hữu ích, chỉ muốn thêm một trường hợp sử dụng.

Trong kịch bản WPF tổng hợp, điều khiển người dùng của bạn có thể sử dụng các tài nguyên được xác định trong bất kỳ cửa sổ / điều khiển cha mẹ nào khác (sẽ lưu trữ điều khiển người dùng này) bằng cách gọi tài nguyên đó là DynamicResource.

Như đã đề cập bởi những người khác, Staticresource sẽ được tra cứu tại thời gian biên dịch. Kiểm soát người dùng không thể tham chiếu đến các tài nguyên được xác định trong điều khiển lưu trữ / cha mẹ. Mặc dù, DynamicResource có thể được sử dụng trong trường hợp này.


3

Lợi ích quan trọng của tài nguyên động

nếu khởi động ứng dụng mất nhiều thời gian, bạn phải sử dụng tài nguyên động, vì tài nguyên tĩnh luôn được tải khi cửa sổ hoặc ứng dụng được tạo, trong khi tài nguyên động được tải khi chúng được sử dụng lần đầu tiên.

Tuy nhiên, bạn sẽ không thấy bất kỳ lợi ích nào trừ khi tài nguyên của bạn cực kỳ lớn và phức tạp.


Đối với DynamicResource, nó chỉ tạo ra sự cố hiệu năng một lần (được sử dụng lần đầu tiên) hay mỗi lần phần tử được sử dụng?
Morgane

trong trường hợp này, hầu hết các trường được sử dụng phải là tài nguyên tĩnh, các trường được sử dụng tùy chỉnh có thể là động, tức là đối với tài nguyên chính là tĩnh và tài nguyên cửa sổ hộp thoại có thể là động
zamoldar

2

Tài nguyên động chỉ có thể được sử dụng khi thuộc tính được đặt trên đối tượng được lấy từ đối tượng phụ thuộc hoặc có thể đóng băng trong đó tài nguyên tĩnh có thể được sử dụng ở bất cứ đâu. Bạn có thể trừu tượng hóa toàn bộ điều khiển bằng cách sử dụng tài nguyên tĩnh.

Tài nguyên tĩnh được sử dụng trong các trường hợp sau:

  1. Khi tài nguyên phản ứng thay đổi trong thời gian chạy là không cần thiết.
  2. Nếu bạn cần một hiệu suất tốt với nhiều tài nguyên.
  3. Trong khi tham chiếu tài nguyên trong cùng một từ điển.

Tài nguyên động:

  1. Giá trị của thuộc tính setter hoặc style setter không được biết cho đến khi runtime
    • Điều này bao gồm hệ thống, ứng dụng, cài đặt dựa trên chủ đề
    • Điều này cũng bao gồm các tài liệu tham khảo về phía trước.
  2. Tham khảo các tài nguyên lớn có thể không tải khi tải trang, cửa sổ, điều khiển người dùng.
  3. Tham khảo các kiểu chủ đề trong một điều khiển tùy chỉnh.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.