必要なバインディングと同様のバインディングを実現する 3 つの方法を次に示します。
1) ラッパー クラス:
public class ProfileUserWrapper : DependencyObject
{
public ProfileUserWrapper(ProfileUser thebrain) { TheUser = thebrain; }
public ProfileUser TheUser { get; private set; }
public Operator User { get { if (_user != null)return _user; return _user = OperatorManager.GetByGuId(TheUser.User_ID); } }
private Operator _user = null;
}
public EntityCollection<ProfileUser> ProfileUsers
ここで、たとえば公開する代わりに、次のようにしますIEnumerable<ProfileUserWrapper>
。
public EntityCollection<ProfileUser> ProfileUsers // your original code
{
get{ if (profile != null) return profile.ProfileUser; else return null;}
set { profile.ProfileUser = value; }
}
public IEnumerable<ProfileUserWrapper> ProfileUsers2
{
get { return ProfileUsers.Select(user => new ProfileUserWrapper(user));
}
次に、ProfileUsers2 にバインドし、バインドの一部を「Address」から「TheUser.Address」に変更する必要がありますが、これはほぼ確実に機能します。
2) 2 つ目は、スマート コンバーターです。たとえば、次のようになります。
public class OperatorPicker : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var pu = value as ProfileUser;
if (pu != null)
return OperatorManager.GetByGuId(pu.User_ID);
return null;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new System.NotImplementedException();
}
}
これほど簡単に書くことはできません。XAML バインディングでコンバーターを使用できるようになりました。
<Window.Resources>
<myextra:OperatorPicker x:Key="conv1" />
</Window.Resources>
<Grid>
<ListBox x:Name="lbxFirst" ItemsSource="{Binding ProfileUsers}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="5" Text="{Binding User_ID}" />
<TextBlock Margin="5" Text="{Binding Login}" />
<TextBlock Margin="5" Text="{Binding Address}" />
<TextBlock Margin="5" Text="{Binding Path=., Converter={StaticResource conv1}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
しかし、このようにして、Operator
オブジェクト自体を取得します。このような方法で返された演算子のプロパティにバインドできるようにするのは非常に困難です.Bindingにはすでにパスが「.」に固定されており、ConverterにProfileUserインスタンスを渡す必要があるため、それを変更することはできません..
3) 3 番目の最も複雑ですが、ラッパーなしで完全に動作するのは、添付プロパティ、コンバーター、および 2 つのバインディングに基づいていますが、2 つの添付プロパティと 1 つの変更コールバックでも実行できます。私は前者の方法を好むので、ここにあります:
public class DummyClass : DependencyObject
{
public static readonly DependencyProperty TheOperatorProperty = DependencyProperty.RegisterAttached(
"TheOperator", typeof(Operator), typeof(DummyClass),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender)
);
public static Operator GetTheOperator(DependencyObject elem) { return (Operator)elem.GetValue(TheOperatorProperty); }
public static void SetTheOperator(DependencyObject elem, Operator value) { elem.SetValue(TheOperatorProperty, value); }
}
... xmlns:myextra="clr-namespace:...." ....
<Window.Resources>
<myextra:OperatorPicker x:Key="conv1" />
</Window.Resources>
<Grid>
<ListBox x:Name="lbxFirst" ItemsSource="{Binding ProfileUsers}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="aparent" Orientation="Horizontal"
myextra:DummyClass.TheOperator="{Binding Path=., Converter={StaticResource conv1}}">
<TextBlock Margin="5" Text="{Binding User_ID}" />
<TextBlock Margin="5" Text="{Binding Login}" />
<TextBlock Margin="5" Text="{Binding Address}" />
<TextBlock Margin="5"
Text="{Binding Path=(myextra:DummyClass.TheOperator).OperatorCodename, ElementName=aparent}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
StackPanel のレベルに新しいバインドがあることに注意してください。これは、テキスト ボックス自体であっても、データ テンプレートの任意の場所に配置できます。コンバーターを介して ProfileUser を Operator に変換する方法に注意してください。はPath=.
必須ではありませんが、バインディングの正確な意味が表示されるように追加しました。最後のテキスト ボックス バインドがどのように指定されているかに注意してください。これは、元のデータではなく、(要素名を介した) 添付プロパティへのバインドです!
今回はすべてをテストしましたが、私の側では動作し、ProfileUser で DependencyObject を継承する必要はありません。それはDummyClass
継承によって満たされます。これを試したら、いつものようにメモを残してください:)