2010-02-22 6 views
3

Silverlight 앱을 만들고 있는데 백그라운드에서 장시간 작업이 진행되는 동안 버튼을 비활성화하고 싶습니다. MVVM을 사용하고 있으므로 ViewModel에는 SearchInProgress라는 속성이 있습니다. 이제 SearchInProgress가 true가 될 때마다 검색 버튼을 비활성화하고 싶습니다. WPF에서 검색 단추에 IsEnabled를 false로 설정하는 DataTrigger를 작성했습니다.Silverlight - 버튼의 IsEnabled 속성을 ViewModel의 속성에 바인딩

슬프게도 DataTriggers는 Silverlight에서 사용할 수 없으므로 다른 해결책을 찾고 있습니다. 나는 VisualStateManager를 가지고 놀려고했지만 아무데도 못 가봤습니다. VSM은 내가 달성하려고하는이 간단한 일에 과잉이라고 생각됩니다.

도움을 주시면 감사하겠습니다.

답변

0

나는 꽤 만족 스럽다. 먼저 LayoutRoot Grid의 'SearchInProgress'와 'Normal'에 두 가지 VSM 상태를 정의했습니다.

 <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="Standard"> 
      <VisualState x:Name="SearchInProgress"> 
       <Storyboard> 
        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SearchButton" Storyboard.TargetProperty="(Control.IsEnabled)"> 
         <DiscreteObjectKeyFrame KeyTime="00:00:00"> 
          <DiscreteObjectKeyFrame.Value> 
           <system:Boolean>False</system:Boolean> 
          </DiscreteObjectKeyFrame.Value> 
         </DiscreteObjectKeyFrame> 
        </ObjectAnimationUsingKeyFrames> 
        <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SearchCancelButton" Storyboard.TargetProperty="(Control.IsEnabled)"> 
         <DiscreteObjectKeyFrame KeyTime="00:00:00"> 
          <DiscreteObjectKeyFrame.Value> 
           <system:Boolean>True</system:Boolean> 
          </DiscreteObjectKeyFrame.Value> 
         </DiscreteObjectKeyFrame> 
        </ObjectAnimationUsingKeyFrames> 
       </Storyboard> 
      </VisualState> 
      <VisualState x:Name="Normal"/> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 

매우 단순하고 적응하기 쉽지만 작동합니다.

나를 데이터 컨텍스트 (뷰 모델)의 속성에 바인딩하고 그에 따라 두 상태 사이를 전환 할 수 있습니다 here에서 나는 DataStateBehavior를 사용하는 상태 사이를 전환하려면 : 내가 지금 할 것 같아요

 <interactivity:Interaction.Behaviors> 
     <exprsamples:DataStateBehavior Binding="{Binding Path=SearchIsInProgress, Mode=TwoWay}" 
             Value="True" 
             TrueState="SearchInProgress" 
             FalseState="Normal"> 
     </exprsamples:DataStateBehavior> 
    </interactivity:Interaction.Behaviors> 

을 VSM의 성능, Blend의 설계 용이성 및 'DataTrigger'메커니즘의 유연성을 최대한 활용하십시오.

0

데이터 모델에 대해 DependencyProperty 또는 INotifyPropertyChanged 인터페이스를 사용한 다음 공용 속성 인 SerachInProgress에 바인딩하십시오. 나는 당신이 당신의 부울의 반대쪽으로 변환하는 Converter를 만들어야 할 수도 있다고 생각합니다.

0

SearchInProgress 속성에 바인딩하지만 변환기를 통해 실행하여 부울을 바꿉니다. 컨버터 변환 기능에서

IsEnabled="{Binding Path=SearchInProgress,Converter={StaticResource YOURCONVERTERHERE}}" 

같은 바인딩, 뭔가에

, 나는 당신이 널 (null) 항목 등을 위해 그 주위를 넣을 확인 어떤 정신으로

return !(value as bool) 

있을 거라고 생각

+0

작은 지저분한. –

1

틀림없이 더 좋은 방법은 Prism2의 DelegateCommand를 검색 버튼에 연결하고 ViewModel에서 CanExecute 메소드를 구현하여 반환하는 것입니다 s! SearchInProgress.

그런 다음 ViewModel이 검색 작업을 시작하면 SearchInProgress가 true로 변경되어 CanExecute가 false를 반환하고 명령에서 RaiseCanExecuteChanged가 호출되어 버튼이 비활성화됩니다. 검색 작업이 ViewModel은 SearchInProgress를 다시 false로 변경하여 CanExecute가 true를 반환 한 다음 RaiseCanExecuteChanged를 다시 호출합니다 (버튼이 활성화 됨)

+1

이 프로젝트를위한 프레임 워크 사용을 피하고 싶습니다. –

0

내가 생각할 수있는 유일한 현명한 해결책은 뷰가 구독하는 ViewModel의 이벤트 "SearchCompleted"를 실행 한 다음 이벤트가 발생할 때 해당 뷰를 변경합니다. 농구를 통해 점프 가지고보다는 SearchInProgress=true

7

그냥 CanSearch 속성을 만들고이 결합하지 왜 IsEnabled=false을 설정합니다. 이 속성은 읽기 전용 (또는 전용 설정자가있을 수 있음)이며 다른 속성은 PropertyChanged 이벤트를 대신 수행 할 수 있습니다.

궁극적으로보기 모델의 핵심은보기에서 논리를 제거한다는 것입니다. 보기를 SearchInProgress에 바인딩하면 (따라서 변환기를 사용하여 IsEnabled에 대해이를 무효화)보기가 일 때 또는 검색 할 수 없으면 을 인식한다는 것을 의미합니다. 그러나 CanSearch 속성에 바인딩하면 뷰 모델이 검색이 활성화되고 뷰가 바보 상태로 남아있을 수있는 경우를 완전히 제어 할 수 있음을 의미합니다.

또는 Blend와 함께 설치된 Blend 비헤이비어 API를 데이터 트리거와 비슷한 것으로 사용할 수 있습니다.

+0

좋은 포인트. 내가 언급 한 두 가지를 살펴볼 것입니다. –

+0

내가 피하고 싶은 것은 검색이 진행 중일 때 비활성화하거나 변경하려는 모든 컨트롤의 CanSearch 속성에 바인딩하는 것입니다. 나는 가능하다면 한 곳에서 그것을 갖고 싶어. –

+0

개인적으로 각 위치에서 XAML 바인딩을 선호하지만 코드가없는 경우 항상 PropertyChanged 이벤트를 추적하고 각 해당 컨트롤에서 IsEnabled 속성을 업데이트 할 수 있습니다. (OneWay 바인딩을 사용하여 속성의 값을 변경하면 바인딩을 제거한다는 점에 유의하십시오) –

0

PRISM dll을 프로젝트에 추가 할 이유가 없습니다. 10 줄의 코드와 2 개의 단위 테스트 만 필요합니다.

그래도 명령 패턴을 사용하고 싶습니다. 에 'ICommand의'와 소요 "명령"연결된 속성을 추가 속성은 설정되어있는 경우 :

  1. 명령을 준수하고 사용하거나 요청으로 버튼을 비활성화합니다.
  2. 명령에서 'Execute'메서드를 호출하는 버튼의 "Click"이벤트에 처리기를 추가합니다.

프리즘에 대한 참고 사항 : 라이브러리가 아프다! 그러나 Composite Application Guidance Book은 MVVM 응용 프로그램을 작성하는 모든 사람에게 필수적인 읽기이며 명령 패턴에 대한 자세한 정보를 제공합니다.

0

명령을 만들어 단추에 바인딩해야합니다. 당신이 찾고있는 모든 것은 런타임에 구워집니다. MVVM Light 및 Prism과 같은 프레임 워크를 사용하면 새 명령을 쉽게 만들 수 있지만 다음과 같이 직접 수행 할 수 있습니다.

ICommand를 구현하는 클래스를 만듭니다. SearchInProgress라는 이름의 개인 bool을 지정하십시오. 검색이 시작되면 SearchInProgress를 true로 설정합니다. 검색이 완료되면 (성공적으로 또는 시간 초과 되었기 때문에 중단되었거나 중단되었습니다) SearchInProgress를 false로 설정합니다. ICommand.CanExecute를 구현하여 SearchInProgress를 반환하십시오. 보기 모델에 ICommand 검색을 노출 한 다음 단추의 명령 속성을보기 모델의 명령에 바인딩하십시오.

사이비 코드 :

public class MySearchCommand : ICommand 
{ 
    public event EventHandler CanExecuteChanged; 
    private bool _searching; 
    private bool SearchInProgress 
    { 
    get { return _searching; } 
    set 
    { 
     if (_searching == value) return; 
     _searching = value; 
     if (CanExecuteChanged != null) CanExecuteChanged(this, EventArgs.Empty); 
    } 

    public bool CanExecute(object param) 
    { return !SearchInProgress } 

    public void Execute(object param) 
    { 
    try 
    { 
     SearchInProgress = true; 
     // search code here including callback to OnSearchCompleted method 
    } 
    catch(Exception ex) 
    { 
     SearchInProgress = false; 
    } 
    } 

    private void OnSearchCompleted(SomeCallbackResult result) 
    { 
    SearchInProgress = false; 
    } 
} 

public class ViewModel : INotifyPropertyChange 
{ 
    public ICommand SearchCommand { get; private set; } 
    public ViewModel() 
    { 
    SearchCommand = new MySearchCommand(); 
    } 
} 

XAML :

나는 이것이 얻을 수있는 GUI에서 동시에 여러 상황을 타개 할 줄 경우 그 그러나, 일 것이라고 생각
<UserControl ....> 
    <UserControl.DataContext> 
    <ViewModel /> 
    </UserControl.DataContext> 
    <Grid> 
    <Button Command={Binding SearchCommand} /> 
    </Grid> 
</UserControl> 
관련 문제