主頁 > .NET開發 > [翻譯] WPF 中用戶控制元件 DataContext/Binding 和依賴屬性的問題

[翻譯] WPF 中用戶控制元件 DataContext/Binding 和依賴屬性的問題

2022-03-25 06:09:51 .NET開發

[翻譯] WPF 中用戶控制元件 DataContext/Binding 和依賴屬性的問題

目錄 提問 回答

User Control DataContext/Binding Issue with Dependency Property WPF

 

[譯者] 獨立觀察員 2022 年 3 月 24 日

提問

ProgrammingDude(asked Dec 8, 2015 at 21:24)

Ok, so my problem is I have a user control. In the xaml I bind some colors to color properties that I have created as shown below.

好,我的問題是,我有一個用戶控制元件,在 Xaml 中,我系結了一些顏色到顏色屬性,如下所示:

<GradientStop x:Name="stop1" Color="{Binding Color1}" Offset="0"/>
<GradientStop x:Name="stop2" Color="{Binding Color2}" Offset="1"/>

 

In my code behind I have a DependencyProperty that I have declared as shown below.

在后臺代碼中,我宣告了一個依賴屬性,如下所示:

public static readonly DependencyProperty IsActiveProperty =
    DependencyProperty.Register("IsActive", typeof(bool), typeof(Bin),
        new PropertyMetadata(new PropertyChangedCallback(Bin.IsActivePropertyChanged)));

 

The dependency property has a PropertyChangedCallback that it calls called IsActivePropertyChanged as shown below.

該依賴屬性有一個 PropertyChangedCallback 方法,名稱為 IsActivePropertyChanged,如下所示:

private static void IsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Bin b = (Bin)d;
    if((bool)e.NewValue)
    {
        b.Color1 = Color.FromArgb(0xFF, 0x3E, 0x3E, 0x3E);
        b.Color2 = Colors.Red;
        b.Color3 = Colors.Red;
        b.Color4 = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
    }
    else
    {
        b.Color1 = Color.FromArgb(0xFF, 0x3E, 0x3E, 0x3E);
        b.Color2 = Color.FromArgb(0xFF, 0x83, 0x83, 0x83);
        b.Color3 = Color.FromArgb(0xFF, 0x63, 0x63, 0x63);
        b.Color4 = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
    }
}

 

If I use the constructor below, the color changes inside of the constructor work fine, however, my IsActivePropertyChangedEvent never gets fired. I am assuming because of the DataContext assignment in the constructor.

如果我使用下面的建構式,在建構式中的顏色改變作業正常,然而,我的 IsActivePropertyChangedEvent 從未被觸發,我估計是因為在建構式中指定了 DataContext,

public Bin()
{
    Color1 = Color.FromArgb(0xFF, 0x3E, 0x3E, 0x3E);
    Color2 = Color.FromArgb(0xFF, 0x83, 0x83, 0x83);
    Color3 = Color.FromArgb(0xFF, 0x63, 0x63, 0x63);
    Color4 = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
    InitializeComponent();
    DataContext = this;
}

 

If I comment out the DataContext assignment and use the constructor below, my Color assignments do not work, but the IsActivePropertyChanged event fires fine.

如果我注釋掉 DataContext 賦值,使用如下的建構式,我的顏色賦值就沒起作用,但 IsActivePropertyChanged 事件能夠被觸發,

public Bin()
{
    Color1 = Color.FromArgb(0xFF, 0x3E, 0x3E, 0x3E);
    Color2 = Color.FromArgb(0xFF, 0x83, 0x83, 0x83);
    Color3 = Color.FromArgb(0xFF, 0x63, 0x63, 0x63);
    Color4 = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
    InitializeComponent();
    //DataContext = this;
}

 

My question is how can i get the binding to work correctly and have my event fire as well. I have tried setting the DataContext="{Binding RelativeSource={RelativeSource Self}}" (instead of setting the DataContext in the code behind) of the items that are bound to the Color Properties in XAML, a rectangle and a polygon, but that didn't seem to work. Thanks in advance for any help.

我的問題就是,怎樣能讓系結和事件觸發都正常作業,我嘗試了為 Xaml 中系結到 Color 屬性的元素設定 DataContext="{Binding RelativeSource={RelativeSource Self}}" (而不是在后臺代碼中設定 DataContext),一個矩形和一個多邊形,但似乎不起作用,提前感謝任何提供的幫助,

 

回答

vesan(answered Dec 9, 2015 at 22:48)

When writing your own control, you shouldn't mess with the DataContext of the control itself.

Instead, on the binding of the GradientStop, you can use RelativeSource={RelativeSource AncestorType=Bin} (assuming Bin is your control). Or you can define a template and use TemplateBinding. Check this answer I wrote a while back for a similar question - it has more detailed description of how this works.

在寫你自己的控制元件時,你不應當把控制元件自身的 DataContext 弄亂,

取而代之的是,在系結 GradientStop 時,你可以使用 RelativeSource={RelativeSource AncestorType=Bin} (假設 Bin 是你的控制元件),或者,你可以定義一個模板并且使用 TemplateBinding,查看我不久之前為一個類似的問題寫的 這個回答 ,其中有關于這如何作業的更多詳細描述,

 

(譯者注:他上面提到的詳細回答如下)

vesan(answered May 28, 2015 at 2:26)

Although this has now been solved there seems to be some, in my opinion, inappropriate use of the DataContext.

When developing a custom reusable control, you should not set DataContext at all. What the DataContext will be, that is for the user of the control to decide, not for the developer. Consider the following common pattern of code:

雖然這個現在已經被解決了(譯者注:另一個回答被標記為答案),在我看來,似乎有一些,對 DataContext  的不正確使用,

當開發一個定制的可復用的控制元件,你根本不應該設定 DataContext  ,DataContext 將會是什么,應當是控制元件使用者來決定的,而不是開發者,思考下面的常見模式代碼:

<Grid DataContext="{Binding Data}">
    <TextBox Text="{Binding TextValue1}" />
    <!-- Some more controls -->
</Grid>

 

Notice that here, you are using the Grid control. The developer of the control (in this case, the WPF team), didn't touch the DataContext at all - that is up to you. What does it mean for you as a control developer? Your DependencyProperty definition is fine, but you shouldn't touch the DataContext. How will you then bind something inside your control to the DependencyProperty value? A good way is using a template (namespaces omitted):

注意這里,你正在使用 Grid 控制元件,控制元件的開發者(這個例子中,是 WPF 團隊),根本沒有碰 DataContext —— 這個是你來用的,那么這對于作為控制元件開發者的你來說意味著什么呢?你的依賴屬性定義是沒問題的,但你不應該碰 DataContext ,那么你之后怎么將控制元件中的一些東西系結到依賴屬性的值呢?一個好的方式就是使用模板(命名空間省略了):

<MyTimePicker>
    <MyTimePicker.Template>
        <ControlTemplate TargetType="MyTimePicker">
            <!-- Stuff in your control -->
            <TextBlock Text="{TemplateBinding Time}" />
            <TextBox Text="{Binding Time, RelativeSource={RelativeSource TemplatedParent}}" />
        </ControlTemplate>
    <MyTimePicker.Template>
</MyTimePicker>

 

Note that TemplateBinding is always one-way only, so if you need any editing at all, you need to use normal binding (as you can see on the TextBox in the example).

This only means that the TextBlock/Box inside your control will get its Time value from your custom control itself, ignoring any DataContext you might have set.

注意 TemplateBinding 總是 one-way 的,所以如果你需要任何編輯,你需要使用普通的 binding (正如你在 TextBox 示例中看到的那樣),

這僅僅意味著你的控制元件內部的 TextBlock/Box 會從你自定義控制元件自身獲得它的 Time 值,忽略任何你可能設定的 DataContext ,

 

Then, when you use the control, you do it like this (added to my first example):

然后,當你使用這個控制元件時,你會這樣做(被添加到我的第一個示例):

<Grid DataContext="{Binding Data}">
    <TextBox Text="{Binding TextValue1}" />
    <!-- Some more controls -->
    <MyTimePicker Time="{Binding TimeValue}" />
</Grid>

 

What just happened here is that the MyTimePicker does not have DataContext set anywhere at all - it gets it from the parent control (the Grid). So the value goes like this: Data-->(binding)-->MyTimePicker.Time-->(template binding)-->TextBlock.Text.

這里發生的是, MyTimePicker 的 DataContext 根本沒有在任何地方被設定,而是從父控制元件(Grid)獲取,所以數值(譯者注:這里是 TimeValue)像這樣流轉:Data-->(binding)-->MyTimePicker.Time-->(template binding)-->TextBlock.Text 

 

And above all, avoid doing this in the constructor of your custom control:

首要的是,避免在你的自定義控制元件的建構式中這樣做:

public MyTimePicker()
{
    InitializeComponent();
    DataContext = this;
}

 

This will override any DataContext set in XAML, which will make binding a huge pain (because you'll have to always set Source manually). The previous example would not work, and this wouldn't work either:

這會覆寫在 Xaml 中設定的任何 DataContext ,會使得系結變成一個大痛苦(因為你將不得不總是手動設定 Source ),之前的示例將不能作業,下面這個也不能作業:

<MyTimePicker DataContext="{Binding Data}" Time="{Binding TimeValue}" />

 

You would think this is OK, but the DataContext will be resolved in the InitializeComponent() call, so the value will be immediately overwritten. So the binding to TimeValue will look for it in the control instead (which will, of course, fail).

你可能認為這是可以的,但 DataContext 會在 InitializeComponent() 呼叫中被重新處理,所以值會被立即重寫,所以目標為 TimeValue 的系結反而會在控制元件中搜尋(這個當然會失敗),

 

Just don't touch the DataContext when developing a control and you'll be fine.

(總之,)開發一個控制元件時就別碰 DataContext ,你將會一切順利,

 

原創文章,轉載請注明: 轉載自 獨立觀察員

本文鏈接地址: [翻譯] WPF 中用戶控制元件 DataContext/Binding 和依賴屬性的問題 [http://dlgcy.com/translate-user-control-datacontext_binding-issue-with-dependency-property-wpf/]

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/449013.html

標籤:.NET技术

上一篇:SECS半導體設備通訊-2 HSMS通信標準

下一篇:dnSpy反編譯除錯

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more