Tokhi
November 16, 2023, 1:42am
1
안녕하세요. 입력박스가 비어있거나 디폴트 값이면 버튼이 좌우로 움직이는 기능을 구현하려고 합니다.
xaml 에서 버튼 이벤트 발생시 해당 텍스트 박스의 값을 체크하면 될 것은데 EventTrigger내에서 다른
컨트롤의 상태를 가져올 수는 없는건가요?? 이 기능은 비하인드코드에서 적용을 해야만 하는건지
도움부탁드립니다.
<Button x:Name="button2" Content="IndividualPrint" HorizontalAlignment="Left" Height="55" Margin="1036,558,0,0" VerticalAlignment="Top" Width="250" FontFamily="Arial Rounded MT Bold" FontSize="24" Background="#7FFF9771" Click="onePrintButton_Click">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderBrush="SkyBlue" BorderThickness="0.5" CornerRadius="5,5,5,5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<!--
이곳에 왼쪽텍스트(textBox1) 값을 참고해서 아래 애니메이션 효과가 일어나도록 조건을
추가했으면 합니다.
-->
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<StaticResource ResourceKey="dataError"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
2 Likes
기본적으로 EventTrigger에서는 로지컬 처리가 불가능 합니다.
대신 DataTrigger로 대체 하여 처리 가능합니다.
다음은 간단한 샘플의 코드 입니다.
[xaml]
<Window.Resources>
<Storyboard x:Key="BtnStartShake">
<DoubleAnimationUsingKeyFrames RepeatBehavior="Forever"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0:0:0"
Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.1"
Value="-5" />
<EasingDoubleKeyFrame KeyTime="0:0:0.2"
Value="5" />
<EasingDoubleKeyFrame KeyTime="0:0:0.3"
Value="-5" />
<EasingDoubleKeyFrame KeyTime="0:0:0.4"
Value="5" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="BtnEndShake">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0:0:0"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="xInputTextBox"
Grid.Column="0"
Height="35"
Text="텍스트를 입력하세요!"
Margin="10"/>
<Button Grid.Column="1"
Height="35"
Width="100"
Content="Click"
Margin="10">
<Button.RenderTransform>
<TranslateTransform/>
</Button.RenderTransform>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<!--텍스트 박스가 기본 문구 이거나-->
<DataTrigger Binding="{Binding ElementName=xInputTextBox, Path=Text, UpdateSourceTrigger=PropertyChanged}"
Value="텍스트를 입력하세요!">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource BtnStartShake}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource BtnEndShake}" />
</DataTrigger.ExitActions>
</DataTrigger>
<!--텍스트 박스가 비어 있거나-->
<DataTrigger Binding="{Binding ElementName=xInputTextBox, Path=Text, UpdateSourceTrigger=PropertyChanged}"
Value="">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource BtnStartShake}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource BtnEndShake}" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
텍스트 박스의 Text 속성 값 기준으로
텍스트 박스에 값이 비 어 있거나,
텍스트 박스에 값이 기본 문구 라면,
버튼이 좌.우로 흔들리도록 처리 된 예제 입니다.
다만, 위 예는 버튼 클릭시 동작이 아닌 텍스트 박스의 값이 변경 될때 트리거가 발생 합니다.
Tokhi:
버튼 이벤트 발생시
작성하신 이 조건과도 같이 부합 되어야 한다면
버튼에 Command를 처리해서 텍스트 박스의 값을 체크하여
원하는 조건인지 판단하는 flag 속성을 바인딩 해서 처리 하셔야 합니다.
위 예시 코드에서 ElementName=xInputTextBox 부분을
조건 판단 유무의 flag속성으로 바인딩을 대체 하면 될 것 같습니다.
7 Likes
Tokhi
November 16, 2023, 11:44pm
3
Tokhi:
ger>
감사합니다. 알려주신 힌트로 클릭이벤트 TESt를 해보았습니다.
근데 이게 DataTrigger 이용시 기존값을 저장하고 있나요??
아래 코드의 CheckData 가 최초 실행시 True , 버튼을 클릭하면 False로 변경되어 정상적으로 버튼이
흔들리는데 이상태에서 재차 버튼을 클릭하면 DataTrigger에서는 값 변경이 없어서 인지 반응을 하지
않습니다. 그래서 차선책으로 일단 False로 변경 후 다시 True로 변경하는 로직을 비하인드에
넣어두면 정삭적으로 여러번 버튼을 클릭해도 버튼이 흔들립니다.
DataTrigger 부분에 뭔가 이전의 바인딩 값을 저장하고 있어서 바뀐 값이 동일하면 트리거가 작동을
안하는 느낌인데, 원래 그런가요??
<XAML>
<DataTrigger Binding="{Binding CheckData}" Value="False">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<StaticResource ResourceKey="dataError"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
public Boolean CheckData
{
get { return checkDataP; }
set { checkDataP = value; OnPropertyChanged("CheckData");
//MessageBox.Show(value.ToString());
}
}
public void oneprintLabel()
{
if (string.IsNullOrEmpty(printTxtP)
|| printTxtP.Equals("출력하고자 하는 바코드를 텍스트로 입력하세요."))
{
CheckData = false;
}
else
{
//생략
}
//OnpropertyChaged는 계속 발생되나
//DataTrigger가 동일한 값을 인지하지 못해 True로 변경, 뭔가 이상함
//false -> false : Trigger 작동 X , false -> true -> false : Trigger 작동
CheckData = true;
}
1 Like
재현할 수 있는 간단한 전체 샘플 소스코드가 있으면 좋을 것 같습니다!
1 Like
이전의 바인딩 값을 저장하고 있는게 아니고
CheckData 속성이 최초 초기값 true에서 → false로 바뀌었을때
트리거가 발동 되면서 스토리보드가 작동 되는 것 입니다.
스토리보드가 끝났다고 다시 CheckData 속성 값이 초기화 되진 않죠
여전히 계속 true이기에 한번 스토리보드는 작동 되었기에 다시 재생 하진 않습니다.
그냥 작성 하신 것 처럼 그냥 다시 true로 설정 하셔도 딱히 이상할건 없습니다.
저 방식이 마음에 안드신다 하면…
비해이비어를 별도로 구성하셔서 버튼 클릭시 조건을 체크해서 스토리보드를 작동해도 됩니다.
다음은 대충 비해이비어를 구현해 보았습니다.
public class WhenStoryboardBehavior : Behavior<ButtonBase>
{
private const string Default_InputText = "텍스트를 입력하세요!";
protected override void OnAttached()
{
AssociatedObject.Click += (_, __) =>
{
if (Storyboard is not null)
{
if (string.IsNullOrWhiteSpace(InputText) ||
InputText is Default_InputText)
{
AssociatedObject.BeginStoryboard(Storyboard);
}
}
};
}
public static readonly DependencyProperty InputTextProperty =
DependencyProperty.Register("InputText",
typeof(string),
typeof(WhenStoryboardBehavior));
public string? InputText
{
get { return base.GetValue(InputTextProperty) as string; }
set { base.SetValue(InputTextProperty, value); }
}
public static readonly DependencyProperty StoryboardProperty =
DependencyProperty.Register("Storyboard",
typeof(Storyboard),
typeof(WhenStoryboardBehavior));
public Storyboard? Storyboard
{
get { return base.GetValue(StoryboardProperty) as Storyboard; }
set { base.SetValue(StoryboardProperty, value); }
}
}
<TextBox x:Name="xInputTextBox"
Grid.Column="0"
Height="35"
Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}"
Margin="10"/>
<Button Grid.Column="1"
Height="35"
Width="100"
Content="Click"
Command="{Binding ClickCommand}"
Margin="10">
<Button.RenderTransform>
<TranslateTransform/>
</Button.RenderTransform>
<bi:Interaction.Behaviors>
<local:WhenStoryboardBehavior InputText="{Binding InputText}"
Storyboard="{StaticResource BtnStartShake}"/>
</bi:Interaction.Behaviors>
</Button>
4 Likes
Tokhi
November 17, 2023, 2:50am
6
아니고 맘에 안들다니요;; 너무 감사하죠~^^;; 다만 제가 아직 초보이다 보니 알려주신 방법으로 구현을 하던중 생각했던 동작이 나오질 않아 이유가 궁금해서 추가질문을 드렸던 겁니다~~^^ 다른 구현방법까지 알려주시고 너무 감사합니다~!
2 Likes
code
November 17, 2023, 2:53am
7
우선 궁금한게 텍스트가 변경 되었을때 버튼이 움직이는 건지
아니면 버튼 클릭 했을때 버튼이 움직이는 건지가 내용으로는 판단이 안되네요.
일반적으로 잘못된 값을 넣는 중간에는 특별히 에러 표시를 안하고
액션( 엔터나 버튼 클릭 ) 했을때
에러를 노티 하는 방식을 많이 쓰는 걸로 알고 있습니다.
텍스트가 변경 되었을때는
위에서 말씀해 주신 거처럼 데이터트리거로 처리 하는게 맞고
액션 했을때는 이벤트 트리거로 해주시면 될거 같습니다.
2 Likes
Tokhi
November 17, 2023, 4:28am
8
안녕하세요. 원 질문이 버튼 클릭 이벤트 트리거에서 해당 조건을 확인해서 버튼이 흔들리는 걸 문의드렸습니다. 버튼이 흔들리는것 까지는 구현했었는데 해당 버튼의 이벤트 트리거에서 textBox의 Text를 어찌가져올 수가 있는지가 핵심 질문내용이었습니다.
aroooong 님께서 eventTrigger에서는 로지컬 처리가 불가하다고 하여 바인딩으로 처리했습니다~!
2 Likes