Avalonia UserControl 접근 문제

안녕하세요. 하나의 Window에 UserControl이 두개 일때 UserControl끼리 정보를 주고 받아야 하는데 계속 아래와 같은 에러가 발생합니다.

image

OperateRate가 예제문의 UserControlA입니다.

값을 강제로 적용하면 정상적으로 값이 넘어가는데 이를 바인딩해서 넘길 수 가 없는건지요??

UserControlA - behind

public UserControlA : UserControl
{
 public static readonly StyledProperty<int> stopSecondsProperty = AvaloniaProperty.Register<UserControlA, int>(nameof(StopSeconds), 0, defaultBindingMode: BindingMode.TwoWay);

public int StopSeconds
{
    get => GetValue(stopSecondsProperty);
    set => SetValue(stopSecondsProperty , value);

}


UserControlB - behind

public UserControlB : UserControl
{
 public static readonly StyledProperty<int> stopProperty = AvaloniaProperty.Register<UserControlB, int>(nameof(StopSecond), 0 ,defaultBindingMode: BindingMode.TwoWay );

 public int StopSecond
 {
     get => GetValue(stopProperty);
     set => SetValue(stopProperty, value);
 }

MainWindow - xml
... 중략 ..
  <controls:UserControlB Name="UserB"/>
  <controls:UserControlA StopSeconds="{Binding #UserB.StopSecond}"/>

<!-- 위 유저컨트롤A에 바인딩하면 에러가 발생. 값을 넣어주면 정상적으로 작동 , 부모Window의 Element로 접근해서 바인딩해도 이미지의 에러발생 -->				
			   
			
	

올려주신 예제 코드는 잘못된 부분이 없어 보이는데 혹시 원본 코드에서 실수하신 게 아닐까요?

안녕하세요. 저도 원본코드에서 뭔가 잘못된게 있나싶어 프로젝트를 새로 생성하고 해봤습니다. 동일한 오류가 발생합니다 ㅠㅠ 뭐가 문제인지 도통모르겠습니다.

방금 다시 보다가 해결했습니다 ㅠㅠ 아무것도 아닌거에 하루종일 삽질했습니다.
아발로니아 자체의 문제인지 모르겠으나 아래와 같이 바꾸니 정상적으로 값이 올라옵니다.

<controls:UserControlB Name=“UserB”/>
<controls:UserControlA StopSeconds=“{Binding #UserB.StopSecond}”/>

이 아니라

<controls:UserControlB Name=“UserB” StopSecond=“{Binding #UserA.StopSeconds}”/>
<controls:UserControlA Name=“UserA” />

1개의 좋아요

StopSeconds StopSecond
axaml쪽에 두 속성 이름이 다른데… 혹시 이것때문이…아닌지…

1개의 좋아요

아 예제만 되고 원소스는 안되네요 ㅎㅎ;;; 다른 원인이 있나봅니다 ㅠㅠ

1개의 좋아요

아, 원인을 찾은 것 같습니다.
실행해보지 않고 추측으로 답변드려 죄송합니다. :sweat_smile:

올려주신 코드를 그대로 복붙해보니 오류가 재현되었는데요.

WPF의 Dependency Property와 마찬가지로 Avalonia의 Styled Property를 정의할 때도 CLR 속성 이름 + Property suffix 규칙을 지켜야 합니다.

즉, 속성 이름은 다음과 같은 형태로 작성되어야 합니다.

[속성이름]Property

관련 공식 문서: Defining Properties | Avalonia Docs

현재 UserControlA에서는 stopSecondsProperty로 선언하셨고,
UserControlB에서는 stopProperty로 선언하셨기 때문에,
UserControlB의 경우 바인딩 대상 속성을 찾지 못하는 문제가 발생한 것입니다.

(재미있는 점은, stopSecondsProperty처럼 CamelCase로 작성한 이름에서는 오류가 발생하지 않는다는 것입니다.)

아래와 같이 속성 이름을 맞춰주시면 잘 동작하시는 것을 확인할 수 있습니다.

public class UserControlA : UserControl
{
	public static readonly StyledProperty<int> StopSecondsProperty = AvaloniaProperty.Register<UserControlA, int>(nameof(StopSeconds), 0, defaultBindingMode: BindingMode.TwoWay);

	public int StopSeconds
	{
		get => GetValue(StopSecondsProperty);
		set => SetValue(StopSecondsProperty, value);

	}
}

public class UserControlB : UserControl
{
	public static readonly StyledProperty<int> StopSecondProperty = AvaloniaProperty.Register<UserControlB, int>(nameof(StopSecond), 0, defaultBindingMode: BindingMode.TwoWay);

	public int StopSecond
	{
		get => GetValue(StopSecondProperty);
		set => SetValue(StopSecondProperty, value);
	}
}

6개의 좋아요

와!!! 정상적으로 컴파일됩니다 ㅠㅠ 명명규칙이 중요할 줄이야 ㅠㅠ 어제 하루동안 이걸 해결하려고 별짓을 다 했는데 너무 속시원합니다!! ㅎㅎ 정말 너무너무 감사합니다~!!!

2개의 좋아요