2010年3月18日木曜日

第26回 タイムラインの削除に対応する

これまで手を抜いて
タイムラインの追加ができても削除ができない状態だったので、
削除をできるようにします。

半分は以前やったリストの選択の回と同じ内容ですが。。

まずOptionDialog.xamlにて、
アイテムを選択できるように、ItemsControlにしていたところをListBoxに変更します。



     <ListBox x:Name="timelines" ItemsSource="{Binding Path=TimelineSettings}"
        IsSynchronizedWithCurrentItem="True"
        ItemContainerStyle="{StaticResource TimelineSettingItemContainer}"
        HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>

リソースで見た目を変更するようにStyleを追加します。
選択時のエフェクトも追加します。


  <Style x:Key="TimelineSettingItemContainer" TargetType="{x:Type ListBoxItem}">
   <Setter Property="Template">
    <Setter.Value>
     <ControlTemplate TargetType="{x:Type ListBoxItem}">
      <GroupBox x:Name="ItemContainer" Header="{Binding Path=TimelineTypeName}" Padding="5">
       <ContentPresenter/>
      </GroupBox>
      <ControlTemplate.Triggers>
       <!--選択アイテムのエフェクト-->
       <Trigger Property="IsSelected" Value="True">
        <Setter TargetName="ItemContainer" Property="BorderThickness" Value="3"/>
        <Setter TargetName="ItemContainer" Property="BorderBrush" Value="DarkGray"/>
       </Trigger>
      </ControlTemplate.Triggers>
     </ControlTemplate>
    </Setter.Value>
   </Setter>
  </Style>

見た目がわかりにくい気もしますが、とりあえずおいておきます。
ControlTemplateに枠を描くようにしたので、
その中に表示される各アイテムのDataTemplateからは枠を削除しています。
あと見た目の関係でちょこちょこいぢっています。

削除コマンドも追加します。


<Button Command="{Binding Path=RemoveTimelineCommand}" CommandParameter="{Binding ElementName=timelines, Path=SelectedItem}">タイムライン削除</Button>

CommandParameterで削除のターゲットを指定しています。
ElementNameで最初に作ったListBoxを指すようにし、
ListBoxのSelectedItemプロパティの値がParameterとして渡されます。

各DataTemplateの中にはBindingGroupが追加されていることに注意してください。


    <StackPanel.BindingGroup>
     <BindingGroup Name="OptionBinding"/>
    </StackPanel.BindingGroup>

BindingGroupにより設定変更の確定、変更のキャンセルを制御していますが、
Listの先までには自動的に伝搬してくれないみたいなので、
(↑つまり以前まではタイムラインのURL書き換えてキャンセルボタンで閉じても反映されていた)
各情報にNameプロパティを追加したBindingGroupを追加することで
同時にCancelなどが伝搬するようにしています。

あとはリストへの追加・削除をキャンセルする方法がわからなかったので、
自前で無理矢理作りました。

OptionViewModelで変更前のリストを持っていて
キャンセルされたら戻しています。


  public void CommitEdit() {
   //特に何もしない
  }

  public void BeginEdit() {
   _timelineSettingsBeforeEdit = new List<TimelineSetting>(TimelineSettings);
  }

  public void CancelEdit() {
   if (TimelineSettings.SequenceEqual(_timelineSettingsBeforeEdit)) {
    return;
   }
   _option.TimelineSettings = new ObservableCollection<TimelineSetting>(_timelineSettingsBeforeEdit);
  }


あとはOptionDialogのイベントから呼び出しています。



  private void Window_Loaded(object sender, RoutedEventArgs e) {
   _target.BeginEdit();
   BindingGroup.BeginEdit();
   PasswordBox.Password = _target.UserInfo.Password;
  }

  private void OkButton_Click(object sender, RoutedEventArgs e) {
   _target.CommitEdit();
   BindingGroup.CommitEdit();
   _target.UserInfo.Password = PasswordBox.Password;
   (this.DataContext as OptionViewModel).Save();
   this.DialogResult = true;
   this.Close();
  }

  private void CancelButton_Click(object sender, RoutedEventArgs e) {
   _target.CancelEdit();
   BindingGroup.CancelEdit();
   this.Close();
  }


今回のコード
http://wtwitter.codeplex.com/SourceControl/changeset/view/43269

0 件のコメント:

コメントを投稿