Добрый день, коллеги!
Пытаюсь разабораться с Binding'ом к ComboBox (оригинально на DataForm, но и на Form тоже пойдет)
После поиска решений в Интернете обнаружил, что многие ссылки идут на
http://blogs.msdn.com/b/kylemc/archive/2010/06/18/combobox-sample-for-ria-services.aspx
Пытаясь модифицировать этот пример не смог сделать так, чтобы SelectItem у ComboBox'а выбирался в зависимости от Item'а в другом ComboBox'е.
MainPage.xaml
<StackPanel Name="LayoutRoot" Background="White">
<!-- Form -->
<Border>
<StackPanel>
<TextBlock Text="Form" Style="{StaticResource FormLabelStyle}" />
<Grid Name="Form">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ex:ComboBoxDataSource Name="ASource" DomainContext="{StaticResource SampleDomainContext}" OperationName="GetAValues" />
<ex:ComboBoxDataSource Name="BSource" DomainContext="{StaticResource SampleDomainContext}" OperationName="GetBValues">
<ex:ComboBoxDataSource.Parameters>
<ex:Parameter ParameterName="a" Value="{Binding SelectedValue, ElementName=AComboBox}" />
</ex:ComboBoxDataSource.Parameters>
</ex:ComboBoxDataSource>
<ex:ComboBoxDataSource Name="CSource" DomainContext="{StaticResource SampleDomainContext}" OperationName="GetCValuesQuery">
<ex:ComboBoxDataSource.Parameters>
<ex:Parameter ParameterName="b" Value="{Binding SelectedValue, ElementName=BComboBox}" />
</ex:ComboBoxDataSource.Parameters>
</ex:ComboBoxDataSource>
<TextBlock Text="Id" Grid.Row="0" Grid.Column="0" Style="{StaticResource FormLabelStyle}" />
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Id}" IsReadOnly="True" Style="{StaticResource FormFieldStyle}" />
<TextBlock Text="A" Grid.Row="1" Grid.Column="0" Style="{StaticResource FormLabelStyle}" />
<ComboBox Name="AComboBox" Grid.Row="1" Grid.Column="1" Style="{StaticResource FormFieldStyle}"
ItemsSource="{Binding Data, ElementName=ASource}"
SelectedItem="{Binding A, Mode=TwoWay}"
ex:ComboBox.Mode="AsyncEager" />
<TextBlock Text="B" Grid.Row="2" Grid.Column="0" Style="{StaticResource FormLabelStyle}" />
<ComboBox Name="BComboBox" Grid.Row="2" Grid.Column="1" Style="{StaticResource FormFieldStyle}"
ItemsSource="{Binding Data, ElementName=BSource}"
SelectedItem="{Binding B, Mode=TwoWay}"
ex:ComboBox.Mode="AsyncEager" />
<TextBlock Text="C" Grid.Row="3" Grid.Column="0" Style="{StaticResource FormLabelStyle}" />
<ComboBox Name="CComboBox" Grid.Row="3" Grid.Column="1" Style="{StaticResource FormFieldStyle}"
ItemsSource="{Binding Data, ElementName=CSource}"
IsEnabled="{Binding IsLoaded}"
SelectedItem="{Binding C, Mode=TwoWay}"
ex:ComboBox.Mode="AsyncEager">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="ComboBoxCId" Text="{Binding Id}" Margin="0,0,10,0" />
<TextBlock x:Name="ComboBoxCText" Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</StackPanel>
</Border>
</StackPanel>
MainPage.xaml.cs
public partial class MainPage : UserControl
{
public MainPage( )
{
InitializeComponent( );
var context = new SampleDomainContext( );
context.Load( context.GetSampleEntitiesQuery( ), ContextLoad, null );
}
private void ContextLoad( LoadOperation<SampleEntity> Results )
{
if( !Results.HasError )
{
Form.DataContext = Results.Entities.FirstOrDefault( );
}
}
}
SampleDomainService.cs
namespace ComboBoxes.Web
{
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
[EnableClientAccess]
public class SampleDomainService: DomainService
{
public IEnumerable<SampleEntity> GetSampleEntities( )
{
return new[ ]
{
new SampleEntity { Id = 1, A = "3", B = "9", C = new EntityC { Id = 27 }, CId = 27 },
};
}
public IEnumerable<string> GetAValues( )
{
return new[ ] { 0, 1, 2, 3, 4 }.Select( I => I.ToString( ) );
}
[Invoke]
public IEnumerable<string> GetBValues( string A )
{
if( A == null )
{
return new string[ 0 ];
}
int seed = int.Parse( A );
if( seed == 0 )
{
return new[ ] { "0" };
}
return new[ ] { 0, seed, seed * 2, seed * 3, seed * 4 }.Select( I => I.ToString( ) );
}
public IEnumerable<EntityC> GetCValues( string B )
{
if( B == null )
{
return new[ ] { 0, 1 * 2, 2 * 3, 3 * 4 }.Select(
I => new EntityC { Id = I } );
}
int seed = int.Parse( B );
if( seed == 0 )
{
return new[ ] { new EntityC { Id = 0 } };
}
return
new[ ] { seed, seed * 2, seed * 3, seed * 4 }.Select(
I => new EntityC { Id = I } );
}
public void UpdateSampleEntity( SampleEntity SampleEntity )
{
// do nothing
}
}
[CustomValidation( typeof( Validation ), "ValidateSampleEntity" )]
public class SampleEntity
{
[Key]
public int Id { get; set; }
[CustomValidation( typeof( Validation ), "ValidateString" )]
public string A { get; set; }
[CustomValidation( typeof( Validation ), "ValidateString" )]
public string B { get; set; }
[Include]
[Association( "Sample_C", "CId", "Id", IsForeignKey = true )]
[CustomValidation( typeof( Validation ), "ValidateAssociation" )]
public EntityC C { get; set; }
public int CId { get; set; }
}
public class EntityC
{
[Key]
public int Id { get; set; }
public string Name
{
get { return Id.ToString( ); }
}
public override bool Equals( object Obj )
{
if( Obj == null )
{
return false;
}
if( Obj is EntityC )
{
return Id == ( (EntityC)Obj ).Id;
}
return false;
}
public override int GetHashCode( )
{
return Id.GetHashCode( );
}
}
}
Весь код из примера (только лишь ComboBoxC модифицирован, чтобы отображать Id и Name и, соответственно, добавлено Property Name в EntityC)
В общем проблема в том, почему, когда в ComboBoxB выбирается значение 9, в ComboBoxС не выбирается значение 27 27, но при этом, если выбрать значение 3 в ComboBoxA, то в ComboBoxB выбирается значение 9.
Спасибо.
Как обычно волшебство RSDN работает — сам спросил — сам ответил!
Решение.
Как я и думал, но ссылки на объект SelectedItem и DataContext должны быть одни и теже (иначе как он выберет объект), чтобы добиться этого вместо
var context = new SampleDomainContext( );
context.Load( context.GetSampleEntitiesQuery( ), ContextLoad, null );
надо писать
var context = Resources[ "SampleDomainContext" ] as SampleDomainContext;
if( context != null )
{
context.Load( context.GetSampleEntitiesQuery( ), ContextLoad, null );
}