[.net] WPF에서 종속성 속성과 연결된 속성의 차이점은 무엇입니까?

WPF에서 (사용자 지정) 종속성 속성과 연결된 속성의 차이점은 무엇입니까? 각각의 용도는 무엇입니까? 구현은 일반적으로 어떻게 다릅니 까?



답변

요약

이 문제에 대한 문서를 거의 또는 전혀 찾지 못했기 때문에 소스 코드를 둘러 보는 데 약간의 시간이 걸렸지 만 여기에 답변이 있습니다.

종속성 속성을 “철학적” 속성이 아닌 일반 속성과 연결된 속성으로 등록하는 것에는 차이가 있습니다 ( 일반 속성은 선언 형식과 파생 형식에서 사용하기위한 것이며 연결된 속성은 다음과 같이 사용됩니다. 임의 DependencyObject 인스턴스 에 대한 확장 ). @MarqueIV가 @ReedCopsey의 답변에 대한 주석에서 알 수 있듯이 “철학적”은 임의의 DependencyObject인스턴스 와 함께 일반 속성을 사용할 수도 있습니다 .

또한 연결된 속성이 “종속성 속성의 유형”이라는 다른 답변에 동의하지 않아야합니다. 이는 오해의 소지가 있기 때문에 종속성 속성의 “유형”이 없기 때문입니다. 프레임 워크는 속성이 첨부 된 것으로 등록되었는지 여부를 신경 쓰지 않습니다. (관련성이 없기 때문에이 정보가 기록되지 않는다는 의미에서) 결정할 수도 없습니다. 사실 모든 속성은 마치 연결된 속성 인 것처럼 등록되지만 일반 속성의 경우 동작을 약간 수정하는 몇 가지 추가 작업이 수행됩니다.

코드 발췌

소스 코드를 직접 살펴 보는 수고를 덜기 위해 여기에 무슨 일이 발생하는지 요약 된 버전이 있습니다.

메타 데이터를 지정하지 않고 속성을 등록 할 때

DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))

호출 과 정확히 동일한 결과를 산출 합니다.

DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass))

그러나 메타 데이터를 지정할 때

DependencyProperty.Register(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });

호출과 동일

var property = DependencyProperty.RegisterAttached(
    name: "MyProperty",
    propertyType: typeof(object),
    ownerType: typeof(MyClass),
    defaultMetadata: new PropertyMetadata
    {
        DefaultValue = "default value",
    });
property.OverrideMetadata(
    forType: typeof(MyClass),
    typeMetadata: new FrameworkPropertyMetadata
    {
        CoerceValueCallback = CoerceCallback,
        DefaultValue = "default value",
        PropertyChangedCallback = ChangedCallback
    });

결론

일반 종속성 속성과 연결된 종속성 속성의 주요 (유일한) 차이점은 DependencyProperty.DefaultMetadata 속성을 통해 사용할 수있는 기본 메타 데이터 입니다. 이것은 Remarks 섹션 에서도 언급됩니다 .

연결되지 않은 속성의 경우 속성이 원래 파생 된 메타 데이터 형식으로 등록 된 경우에도이 속성에서 반환 된 메타 데이터 형식을 PropertyMetadata 형식의 파생 된 형식으로 캐스팅 할 수 없습니다 . 원래 파생 된 메타 데이터 유형을 포함하여 원래 등록 된 메타 데이터를 원하면 GetMetadata (Type)를 대신 호출 하여 원래 등록 유형을 매개 변수로 전달하십시오.

연결된 속성의 경우이 속성이 반환하는 메타 데이터의 유형은 원래 RegisterAttached 등록 메서드에 제공된 유형과 일치합니다 .

이것은 제공된 코드에서 명확하게 볼 수 있습니다. 등록 메소드에도 약간의 힌트가 숨겨져 있습니다. 즉 RegisterAttached, 메타 데이터 매개 변수의 경우 이름 defaultMetadata이이고 Register이름이 typeMetadata입니다. 연결된 속성의 경우 제공된 메타 데이터가 기본 메타 데이터가됩니다. 그러나 일반 속성의 경우 기본 메타 데이터는 항상 (제공된 메타 데이터에서 또는 자동으로) 설정된 PropertyMetadata만 있는의 새 인스턴스입니다 DefaultValue. 에 대한 후속 호출 만 OverrideMetadata실제로 제공된 메타 데이터를 사용합니다.

결과

주요 실질적인 차이는 규칙적인 속성의 경우에 있다는 것입니다 CoerceValueCallbackPropertyChangedCallback적용 할 수있는 유일한 소유자 유형으로 선언 된 형태에서 파생 된 유형 등에 대한 연결된 속성에 대한 그들은있는 거 적용 가능한 모든 종류. 예 :이 시나리오에서 :

var d = new DependencyObject();
d.SetValue(SomeClass.SomeProperty, "some value");

등록 PropertyChangedCallback 호출되는 속성이 연결된 속성으로 등록 된 경우 만 호출되지 않습니다 이 일반 재산으로 등록 된 경우. 동일하게갑니다 CoerceValueCallback.

두 번째 차이점은 OverrideMetadata제공된 유형이 DependencyObject. 실제로는 일반 속성의 소유자 유형 에서 파생되어야DependencyObject 하는 반면 연결된 속성의 경우 모든 유형 (정적 클래스, 구조체, 열거 형, 대리자 등)이 될 수 있습니다.

보충

@MarqueIV의 제안 외에도 여러 경우에 일반 속성과 연결된 속성이 XAML 에서 사용할 수있는 방식이 다르다는 의견을 접했습니다 . 즉, 일반 속성에는 연결된 속성에 필요한 명시 적 이름 구문과 달리 암시 적 이름 구문이 필요합니다. 이것은 기술적으로 사실 이 아니지만 실제로는 일반적으로 그렇습니다 . 명확성을 위해 :

<!-- Implicit property name -->
<ns:SomeClass SomeProperty="some value" />

<!-- Explicit property name -->
<DependencyObject ns:SomeClass.SomeProperty="some value" />

에서 순수 XAML 이 구문의 사용을 규율하는 유일한 규칙은 다음과 같다 :

  • 이 요소가 나타내는 클래스 에 해당 이름 의 CLR 속성 이있는 경우에만 요소에 암시 적 이름 구문을 사용할 수 있습니다.
  • 명시 이름 구문 요소에 사용될 수있는 경우에만 그리고 만약 전체 이름의 첫 번째 부분으로 지정된 클래스 적절한 정적 노출 GET / 설정 방법 (라고도 접근 성명의 두 번째 부분과 일치하는 이름)

이러한 조건을 충족하면 지원 종속성 속성이 일반으로 등록되었는지 연결되었는지 여부에 관계없이 해당 구문을 사용할 수 있습니다.

이제 언급 된 오해는 대부분의 자습서 (스톡 Visual Studio 코드 조각 과 함께 ) 에서 일반 종속성 속성에 대해 CLR 속성 을 사용 하고 연결된 항목에 대한 접근자를 가져 오거나 설정 하도록 지시하기 때문에 발생 합니다. 그러나 동시에 둘 다 사용하는 것을 막을 수는 없으므로 원하는 구문을 사용할 수 있습니다.


답변

연결된 속성은 종속성 속성의 한 유형입니다. 차이점은 사용 방법에 있습니다.

연결된 속성을 사용하면 속성이 사용중인 클래스와 동일하지 않은 클래스에 정의됩니다. 일반적으로 레이아웃에 사용됩니다. 좋은 예는 Panel.ZIndex 또는 Grid.Row입니다-이것을 컨트롤 (예 : Button)에 적용하지만 실제로는 Panel 또는 Grid에서 정의됩니다. 속성은 버튼의 인스턴스에 “연결”됩니다.

예를 들어 컨테이너는 모든 UI 요소에서 사용할 수있는 속성을 만들 수 있습니다.

구현 차이에 관해서는 기본적으로 속성을 정의 할 때 Register 대 RegisterAttached를 사용하는 것입니다.


답변

연결된 속성은 기본적으로 그리드가 있고 grid.row가있는 경우와 같이 기본적으로 그리드 요소의 연결된 속성으로 간주됩니다. 또한이 속성을 texbox, button 등에서 사용하여 설정할 수 있습니다. 그리드에 배치하십시오.

종속성 속성은 기본적으로 다른 클래스에 속하고 다른 클래스에서 사용되는 속성과 같습니다. 예 : 여기에 사각형이있는 것처럼 높이와 너비는 사각형의 일반 속성이지만 왼쪽과 상단은 Canvass 클래스에 속하므로 종속성 속성입니다.


답변

연결된 속성은 특별한 종류의 DependencyProperties입니다. 이 값에 대해 아무것도 모르는 객체에 값을 첨부 할 수 있습니다. 이 개념의 좋은 예는 레이아웃 패널입니다. 각 레이아웃 패널에는 하위 요소를 정렬하기 위해 서로 다른 데이터가 필요합니다. Canvas에는 Top과 Left가 필요하고 DockPanel에는 Dock 등이 필요합니다. 자신 만의 레이아웃 패널을 작성할 수 있으므로 목록은 무한합니다. 따라서 모든 WPF 컨트롤에 이러한 속성을 모두 포함 할 수는 없습니다. 솔루션은 연결된 속성입니다. 특정 컨텍스트에서 다른 컨트롤의 데이터를 필요로하는 컨트롤에 의해 정의됩니다. 예를 들어 상위 레이아웃 패널에 의해 정렬되는 요소입니다.


답변

클래스 자체에서 연결된 속성을 정의하거나 다른 클래스에서 정의 할 수 있다고 생각합니다. 우리는 항상 연결된 속성을 사용하여 표준 Microsoft 컨트롤을 확장 할 수 있습니다. 그러나 종속성 속성은 사용자 지정 컨트롤에서 정의합니다. 예를 들어 표준 컨트롤에서 컨트롤을 상속하고 자신의 컨트롤에서 종속성 속성을 정의하여 사용할 수 있습니다. 이는 연결된 속성을 정의하는 것과 동일하며 표준 컨트롤에서이 연결된 속성을 사용합니다.


답변