Có thể đặt mã phía sau một từ điển tài nguyên trong WPF để xử lý sự kiện không?


147

Có thể đặt mã đằng sau một từ điển tài nguyên trong WPF. Ví dụ: trong một điều khiển người dùng cho một nút bạn khai báo nó trong XAML. Mã xử lý sự kiện cho nút bấm được thực hiện trong tệp mã phía sau điều khiển. Nếu tôi tạo một mẫu dữ liệu bằng một nút, làm thế nào tôi có thể viết mã xử lý sự kiện cho nút đó nhấp vào trong từ điển tài nguyên.


1
Cách chính xác để làm điều này là sử dụng một lệnh, nó cũng cung cấp cho bạn khả năng kích hoạt và vô hiệu hóa nút, trong khi bạn có thể làm theo cách mà một số câu trả lời đã gợi ý cho tôi về một vụ hack.
Aran Mulholland

Câu trả lời:


209

Tôi nghĩ những gì bạn đang hỏi là bạn muốn có một tệp mã phía sau cho ResourceDipedia. Bạn hoàn toàn có thể làm điều này! Thực tế, bạn làm điều đó giống như đối với một Cửa sổ:

Giả sử bạn có một ResourceDipedia có tên MyResourceDipedia. Trong tệp MyResourceDipedia.xaml của bạn, đặt thuộc tính x: Class vào phần tử gốc, như vậy:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="MyCompany.MyProject.MyResourceDictionary"
                    x:ClassModifier="public">

Sau đó, tạo một mã phía sau tệp có tên MyResourceDipedia.xaml.cs với khai báo sau:

namespace MyCompany.MyProject
{
    partial class MyResourceDictionary : ResourceDictionary
    { 
       public MyResourceDictionary()
       {
          InitializeComponent();
       }     
       ... // event handlers ahead..
    }
}

Và bạn đã hoàn thành. Bạn có thể đặt bất cứ điều gì bạn muốn vào mã phía sau: phương thức, thuộc tính và trình xử lý sự kiện.

== Cập nhật cho ứng dụng Windows 10 ==

Và chỉ trong trường hợp bạn đang chơi với UWP, có một điều nữa cần lưu ý:

<Application x:Class="SampleProject.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>

                <!-- This will NOT work -->
                <!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->

                <!-- Create instance of your custom dictionary instead of the above source reference -->
                <rd:MyResourceDictionary />

            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

</Application>

7
Là một phụ lục cho câu trả lời của ageektrapping: Hãy chắc chắn rằng bạn đặt tên đủ điều kiện của lớp cơ sở mã hóa của bạn trong thuộc tính x: Class. x:Class="MyCompany.MyProject.MySubFolder1.MyResourceDictionary"Mặt khác, nếu bạn chỉ đặt x: Class = "MyResourceDipedia", trình phân tích cú pháp xaml sẽ không tìm thấy lớp của bạn.
viggity

29
Hãy chắc chắn rằng bạn cung cấp một hàm tạo mặc định trong bộ mã lớp một phần và đảm bảo rằng nó gọi InitializeComponent (). (Trong trường hợp của tôi, tôi đã sử dụng MEF để xuất từ ​​điển tài nguyên.)
Scott Whitlock

4
Đoạn mã cập nhật cho bình luận nâng cao. Tôi cảm thấy cần phải hoàn thành câu trả lời; một lỗi phổ biến. Tôi đã làm nó ngay bây giờ :) Hoàn nguyên nếu bạn không thích nó. Cảm ơn câu trả lời.
Gishu

2
Lưu ý rằng (ít nhất là trong wp8.1), điều này không còn hợp lệ và bạn phải tạo một điều khiển người dùng tùy chỉnh mà các tài liệu tham khảo từ nguồn của bạn
Jared

9
Bạn cũng sẽ phải thiết lập Hành động xây dựng trên tệp XAML của ResourceDipedia thành "Trang", nếu không, lệnh gọi LaunchizeComponent () sẽ không được biên dịch. (Các tệp XAML của ResourceDixi thường được đặt thành "Tài nguyên" theo mặc định.)
user1454265

9

Tôi không đồng ý với "ageektrapping" ... sử dụng phương pháp của một lớp một phần không phải là một thực hành tốt. Mục đích của việc tách Từ điển ra khỏi trang sau đó là gì?

Từ mã phía sau, bạn có thể truy cập ax: Tên phần tử bằng cách sử dụng:

Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
   ...
}

Bạn có thể thực hiện việc này trong phương thức OnApplyTemplate nếu bạn muốn kết nối với các điều khiển khi điều khiển tùy chỉnh của bạn tải. OnApplyTemplate cần được ghi đè để làm điều này. Đây là một thực tế phổ biến và cho phép phong cách của bạn bị ngắt kết nối khỏi điều khiển. (Kiểu không nên phụ thuộc vào điều khiển, nhưng điều khiển nên phụ thuộc vào kiểu có).


7
Phobis Tôi nghĩ rằng mục đích tách từ điển ra khỏi trang là về khả năng sử dụng lại và khả năng đọc của trang chính xaml. Các giải pháp trên làm việc cho tôi quá.
sứt mẻ

5

Gishu - trong khi điều này có vẻ là "thực tế thường không được khuyến khích" Đây là một lý do bạn có thể muốn làm điều đó:

Hành vi tiêu chuẩn cho các hộp văn bản khi chúng lấy nét là để dấu mũ được đặt ở cùng vị trí với khi điều khiển bị mất tiêu điểm. Nếu bạn muốn trong toàn bộ ứng dụng của mình rằng khi người dùng tab vào bất kỳ hộp văn bản nào thì toàn bộ nội dung của hộp văn bản được tô sáng thì thêm một trình xử lý đơn giản trong từ điển tài nguyên sẽ thực hiện thủ thuật.

Bất kỳ lý do nào khác mà bạn muốn hành vi tương tác người dùng mặc định khác với hành vi bên ngoài hộp có vẻ như là ứng cử viên tốt cho mã phía sau trong từ điển tài nguyên.

Hoàn toàn đồng ý rằng bất cứ điều gì là chức năng ứng dụng cụ thể không nên nằm trong một mã phía sau của một từ điển tài nguyên.


0

XAML là để xây dựng các biểu đồ đối tượng không chứa mã.
Mẫu dữ liệu được sử dụng để chỉ ra cách hiển thị đối tượng người dùng tùy chỉnh trên màn hình ... (ví dụ: nếu đó là mục hộp danh sách) không phải là một phần của lĩnh vực chuyên môn của mẫu dữ liệu. Vẽ lại giải pháp ...


kết luận: Bạn có đề nghị sử dụng tài nguyên dic với mã phía sau hay không ?? Tôi chưa bao giờ sử dụng nó, tôi nghi ngờ.
Shimmy Weitzhandler 30/03/2016

1
Tôi sẽ không - với tôi nó không cảm thấy đúng. Một từ điển sẽ trả về giá trị cho các khóa cụ thể. Trong trường hợp của OP, gói mã với mẫu dữ liệu .. Tôi muốn thử một cách tiếp cận khác .. ví dụ sử dụng mô hình Lệnh. Tôi cần biết thêm chi tiết về vấn đề của OP để đề xuất một giải pháp khác.
Gishu

1
Hoàn toàn không đồng ý. Với MVVM, có một kịch bản có mã phía sau cực kỳ hữu ích: phát triển các thuộc tính đính kèm. Làm cho nó hoạt động với mã phía sau, sau đó chuyển nó sang một thuộc tính đính kèm. Điều này nhanh hơn nhiều so với việc đơn giản là phát triển tài sản đính kèm từ đầu, trừ khi bạn có bộ não có kích thước của Manhattan.
Contango
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.