Josh Smithのmvvmワークスペースの例(顧客ビュー)に続いて、私はメインウィンドウとObservableCollection "ChatTabViewModel"を含むメインウィンドウモデルを持っています。
internal class FriendsListViewModel : ObservableObject
{
#region bound properties
private ICollectionView viewfriends;
private ObservableCollection _chatTab;
...
#endregion
}
私はこのようなxamlでこのコレクションに専用の領域を持っています:
そして、私のリソース辞書で:
<button
Command="{Binding Path=CloseCommand}"
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontFamily="Courier"
FontSize="9"
FontWeight="Bold"
Margin="0,1,0,0"
Padding="0"
VerticalContentAlignment="Bottom"
Width="16" Height="16"
/>
ユーザーイベントでは、私のコレクションに新しいChattabViewModelを追加し、それに関連するビューがメインウィンドウに表示されます。
しかし、ChattabViewのスクロールバーにアタッチされたプロパティを追加しようとすると、このプロパティは最初のChattabViewModelインスタンスにのみアタッチされ、他のタブはアタッチされたプロパティにバインドされません。 ChattabView XAMLは次のとおりです。
添付されたプロパティのコード
namespace GtalkOntre.View
{
///
/// Util class to scroll down when a new message is added.
///
/// attached property called ScrollOnNewItem that when set to true hooks into the INotifyCollectionChanged events of the itemscontrol items source and upon detecting a new item, scrolls the scrollbar to it.
public class ItemsControlBehavior
{
static Dictionary Associations = new Dictionary();
public static bool GetScrollOnNewItem(DependencyObject obj)
{
return (bool)obj.GetValue(ScrollOnNewItemProperty);
}
public static void SetScrollOnNewItem(DependencyObject obj, bool value)
{
obj.SetValue(ScrollOnNewItemProperty, value);
}
public static DependencyProperty ScrollOnNewItemProperty =
DependencyProperty .RegisterAttached(
"ScrollOnNewItem",
typeof(bool),
typeof(ItemsControlBehavior),
new UIPropertyMetadata(false, OnScrollOnNewItemChanged));
public static void OnScrollOnNewItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var mycontrol = d as ItemsControl;
if (mycontrol == null) return;
bool newValue = (bool)e.NewValue;
if (newValue)
{
mycontrol.Loaded += MyControl_Loaded;
mycontrol.Unloaded += MyControl_Unloaded;
}
else
{
mycontrol.Loaded -= MyControl_Loaded;
mycontrol.Unloaded -= MyControl_Unloaded;
if (Associations.ContainsKey(mycontrol))
Associations[mycontrol].Dispose();
}
}
static void MyControl_Unloaded(object sender, RoutedEventArgs e)
{
var mycontrol = (ItemsControl)sender;
Associations[mycontrol].Dispose();
mycontrol.Unloaded -= MyControl_Unloaded;
}
static void MyControl_Loaded(object sender, RoutedEventArgs e)
{
var mycontrol = (ItemsControl)sender;
var incc = mycontrol.Items as INotifyCollectionChanged;
if (incc == null) return;
mycontrol.Loaded -= MyControl_Loaded;
Associations[mycontrol] = new Capture(mycontrol);
}
class Capture : IDisposable
{
public ItemsControl mycontrol { get; set; }
public INotifyCollectionChanged incc { get; set; }
public Capture(ItemsControl mycontrol)
{
this.mycontrol = mycontrol;
incc = mycontrol.ItemsSource as INotifyCollectionChanged;
incc.CollectionChanged +=incc_CollectionChanged;
}
void incc_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
ScrollViewer sv = mycontrol.Parent as ScrollViewer;
sv.ScrollToBottom();
}
}
public void Dispose()
{
incc.CollectionChanged -= incc_CollectionChanged;
}
}
}
}
だから、なぜchattabviewmodelコレクションの最初の "chattabview"が発生したときに、接続プロパティは一度だけバインドされますか?したがって、最初のchattabviewモデルでのみ動作します。
私がそれらをすべて閉じると、接続されたプロパティはchattabviewmodelの最後のインスタンスでアンバインドされ、新しい最初のchattabviewmodelを追加するとプロパティが正しくバインドされます。したがって、mainwindowviewmodelの "chattabviewmodel"コレクションの最初のインスタンスと最後のインスタンスでのみトリガされます。
1週間の検索の後、私は今、少し辛いです...
これまでの私の仮説は、問題は辞書リソースのビューモデルにビューを設定する方法に関連している可能性があります。ビューが共有され、最初のスクロールバーのみが反応する可能性があります。 DataTemplateタグに x:Shared = false
属性を追加しようとしましたが、何も変更されませんでした。