เป็นไปได้ไหมที่จะตั้งรหัสหลังพจนานุกรมทรัพยากรใน WPF สำหรับจัดการเหตุการณ์?


147

เป็นไปได้ไหมที่จะตั้งรหัสหลังพจนานุกรมทรัพยากรใน WPF ตัวอย่างเช่นใน usercontrol สำหรับปุ่มที่คุณประกาศใน XAML รหัสการจัดการเหตุการณ์สำหรับการคลิกปุ่มเสร็จสิ้นในไฟล์โค้ดด้านหลังตัวควบคุม ถ้าฉันจะสร้างเทมเพลตข้อมูลด้วยปุ่มฉันจะเขียนโค้ดตัวจัดการเหตุการณ์สำหรับการคลิกปุ่มภายในพจนานุกรมทรัพยากรได้อย่างไร


1
วิธีที่ถูกต้องในการทำเช่นนี้คือการใช้คำสั่งมันยังให้ความสามารถในการเปิดใช้งานและปิดการใช้งานปุ่มในขณะที่คุณสามารถทำได้วิธีที่คำตอบบางคำแนะนำว่ามันมีกลิ่นของแฮ็ค
Aran Mulholland

คำตอบ:


209

ฉันคิดว่าสิ่งที่คุณถามคือคุณต้องการไฟล์ code-behind สำหรับ ResourceDictionary คุณสามารถทำสิ่งนี้โดยสิ้นเชิง! ในความเป็นจริงคุณทำแบบเดียวกับ Window:

สมมติว่าคุณมี ResourceDictionary ที่ชื่อว่า MyResourceDictionary ในไฟล์ MyResourceDictionary.xaml ของคุณให้ใส่แอตทริบิวต์ x: Class ในองค์ประกอบรูทดังนี้:

<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">

จากนั้นสร้างโค้ดที่อยู่หลังไฟล์ชื่อ MyResourceDictionary.xaml.cs พร้อมกับประกาศต่อไปนี้

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

และคุณทำเสร็จแล้ว คุณสามารถใส่อะไรก็ได้ที่คุณต้องการในโค้ดด้านหลัง: เมธอดคุณสมบัติและตัวจัดการเหตุการณ์

== อัปเดตสำหรับแอป Windows 10 ==

และในกรณีที่คุณกำลังเล่นกับUWPมีอีกสิ่งหนึ่งที่ต้องระวัง:

<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
ในฐานะที่เป็นภาคผนวกของคำตอบของ ageektrapped: ตรวจสอบให้แน่ใจว่าคุณใส่ชื่อเต็มของคลาส codebehind ในแอตทริบิวต์ x: Class x:Class="MyCompany.MyProject.MySubFolder1.MyResourceDictionary"มิฉะนั้นถ้าคุณเพียงแค่ใส่ x: Class = "MyResourceDictionary" ตัวแยกวิเคราะห์ xaml จะไม่พบชั้นเรียนของคุณ
viggity

29
ตรวจสอบให้แน่ใจว่าคุณได้จัดทำ Constructor เริ่มต้นใน codebehind คลาสบางส่วนและตรวจสอบให้แน่ใจว่าได้เรียก InitializeComponent () (ในกรณีของผมผมก็ใช้ MEF เพื่อส่งออกพจนานุกรมทรัพยากร.)
สกอตต์วิทล็อค

4
อัปเดตข้อมูลโค้ดเพื่ออัปเดตความคิดเห็นแล้ว ฉันรู้สึกว่าจำเป็นต้องตอบคำถามให้เสร็จ ข้อผิดพลาดทั่วไป ฉันทำตอนนี้ :) เปลี่ยนกลับถ้าคุณไม่ชอบ ขอบคุณสำหรับคำตอบ.
Gishu

2
โปรดทราบว่า (อย่างน้อยใน wp8.1) สิ่งนี้ไม่ถูกต้องอีกต่อไปและคุณจะต้องสร้างการควบคุมผู้ใช้ที่กำหนดเองที่การอ้างอิงพจนานุกรมของคุณ
Jared

9
คุณจะต้องตั้งค่า Build Action บนไฟล์ XAML ของ ResourceDictionary เป็น "หน้า" มิฉะนั้นการเรียก InitializeComponent () จะไม่คอมไพล์ (โดยปกติแล้วไฟล์ ResourceDictionary XAML จะถูกตั้งค่าเป็น "ทรัพยากร" โดยค่าเริ่มต้น)
user1454265

9

ฉันไม่เห็นด้วยกับ "ageektrapped" ... การใช้วิธีการบางส่วนของชั้นเรียนไม่ใช่วิธีปฏิบัติที่ดี อะไรคือวัตถุประสงค์ของการแยกพจนานุกรมออกจากหน้าเว็บ

จากด้านหลังโค้ดคุณสามารถเข้าถึงขวาน: องค์ประกอบชื่อโดยใช้:

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

คุณสามารถทำเช่นนี้ในวิธีการ OnApplyTemplate ถ้าคุณต้องการที่จะควบคุม hookup โหลดควบคุมแบบกำหนดเองเมื่อคุณ OnApplyTemplate จะต้องถูกแทนที่ด้วยการทำเช่นนี้ นี่เป็นวิธีปฏิบัติทั่วไปและอนุญาตให้สไตล์ของคุณไม่เชื่อมต่อกับส่วนควบคุม (สไตล์ไม่ควรขึ้นอยู่กับการควบคุม แต่การควบคุมควรขึ้นอยู่กับการมีสไตล์)


7
ฉันคิดว่าจุดประสงค์ของการแยกพจนานุกรมออกจากหน้านั้นเป็นเรื่องเกี่ยวกับความสามารถในการนำกลับมาใช้ใหม่และการอ่านของหน้าหลัก xaml วิธีแก้ปัญหาข้างต้นก็ใช้ได้สำหรับฉันเช่นกัน
cleftheris

5

Gishu - ในขณะนี้อาจดูเหมือนว่า "โดยทั่วไปไม่ได้รับการสนับสนุนการปฏิบัติ" นี่คือเหตุผลหนึ่งที่คุณอาจต้องการ:

พฤติกรรมมาตรฐานสำหรับกล่องข้อความเมื่อพวกเขาได้รับการโฟกัสคือการวางเครื่องหมายรูปหมวกที่ตำแหน่งเดียวกันกับเมื่อตัวควบคุมสูญเสียโฟกัส หากคุณต้องการตลอดทั้งแอปพลิเคชันของคุณว่าเมื่อผู้ใช้แท็บไปยังกล่องข้อความใด ๆ ที่มีการเน้นเนื้อหาทั้งหมดของกล่องข้อความแล้วเพิ่มตัวจัดการอย่างง่ายในพจนานุกรมทรัพยากรจะทำเคล็ดลับ

เหตุผลอื่น ๆ ที่คุณต้องการให้พฤติกรรมการโต้ตอบกับผู้ใช้เริ่มต้นแตกต่างจากพฤติกรรมนอกกรอบดูเหมือนจะเป็นตัวเลือกที่ดีสำหรับรหัสที่อยู่ในพจนานุกรมทรัพยากร

เห็นด้วยอย่างเต็มที่ว่าสิ่งใดก็ตามที่ฟังก์ชั่นการใช้งานเฉพาะไม่ควรอยู่ในโค้ดด้านหลังของพจนานุกรมทรัพยากร


0

XAML ใช้สำหรับสร้างกราฟวัตถุที่ไม่มีรหัส
เทมเพลตข้อมูลใช้เพื่อระบุว่าผู้ใช้ - วัตถุที่กำหนดเองจะแสดงผลบนหน้าจออย่างไร ... (เช่นถ้าเป็นรายการกล่องรายการ) พฤติกรรมไม่ได้เป็นส่วนหนึ่งของพื้นที่ความเชี่ยวชาญของเทมเพลตข้อมูล วาดโซลูชันใหม่ ...


ข้อสรุป: คุณจะแนะนำให้ใช้ทรัพยากร dic ด้วยรหัสที่อยู่ด้านหลังหรือไม่? ฉันไม่เคยใช้มันฉันสงสัย
Shimmy Weitzhandler

1
ฉันจะไม่ - สำหรับฉันมันไม่รู้สึกถูกต้อง พจนานุกรมควรคืนค่าสำหรับคีย์เฉพาะ ในกรณีของ OP การรวมรหัสกับเทมเพลต .. ฉันอยากลองใช้วิธีอื่น .. ใช้ตัวแบบคำสั่งเป็นต้น ฉันต้องการรายละเอียดเพิ่มเติมเกี่ยวกับปัญหาของ OP เพื่อแนะนำ diff soln
Gishu

1
ไม่เห็นด้วยอย่างสิ้นเชิง ด้วย MVVM มีสถานการณ์หนึ่งที่การมีโค้ดด้านหลังมีประโยชน์อย่างยิ่งคือการพัฒนาคุณสมบัติที่แนบมา ทำให้มันทำงานกับโค้ดที่อยู่ด้านหลังจากนั้นพอร์ตไปยังคุณสมบัติที่แนบ นี่คือเร็วกว่าเพียงแค่การพัฒนาทรัพย์สินที่แนบมาตั้งแต่เริ่มต้นเว้นแต่ว่าคุณมีสมองขนาดแมนฮัตตัน
Contango
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.