简体   繁体   中英

XAML inconsistent binding

I have a custom UserControl called ReferencedItem . It should take a Guid called ItemId. It is implemented as such:

private static void OnItemIdChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs dpArgs)
{
    //Do something
}

public static readonly DependencyProperty ItemIdProperty = DependencyProperty.Register("ItemId", typeof(Guid?), typeof(ReferencedItem), new FrameworkPropertyMetadata(
    // use an empty Guid as default value
    Guid.Empty,
    // tell the binding system that this property affects how the control gets rendered
    FrameworkPropertyMetadataOptions.AffectsRender,
    // run this callback when the property changes
    OnItemIdChanged
));

public Guid? ItemId
{
    get { return (Guid?)GetValue(ItemIdProperty); }
    set { SetValue(ItemIdProperty, value); }
}

public ReferencedItem()
{
    InitializeComponent();
    ViewModel = new ReferencedItemCtrlViewModel();
    DataContext = ViewModel;
}

The ItemsSource will be made up of Reference objects defined as:

public class Reference
{
    public Guid Id { get; set; }
}

Now when binding this ReferencedItem the value is not set as intended. Here is the code I want to work, but does not bind as intended:

<ItemsControl x:Name="ReferenceStack" ItemsSource="{Binding References}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <local:ReferencedItem ItemId="{Binding Id}" Height="30" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

I have tried:

 <local:ReferencedItem ItemId="128d48f0-f061-49fb-af49-b8e4ef891d03" Height="30" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>

This works as expected, the OnItemIdChanged method is triggered.

<Label Content="{Binding Id}" HorizontalAlignment="Left" VerticalAlignment="Top" Height="30" Width="90"/>

This works as expected, a label is rendered with the Id.

Is there something I'm missing here? From what I can tell the data is available at bind time -- it just doesn't bind under the exact conditions I need it to :)

Thanks for any input!

EDIT:

Here is the code-behind for ReferencedItemList , the first block of XAML posted above:

public partial class ReferencedItemList : UserControl
{
    protected ReferencedItemListCtrlViewModel ViewModel;

    public ReferencedItemList()
    {
        InitializeComponent();
        ViewModel = new ReferencedItemListCtrlViewModel();
        DataContext = ViewModel;
    }

    public void Load(Guid id, string name)
    {
        ViewModel.Load(id, name);
        //ReferenceStack.ItemsSource = ViewModel.References;
    }
}

The commented line has been experimented with in place of the ItemsSource="{Binding References}" that was defined in the XAML.

I don't think I can successfully post the code for ReferencedItemListCtrlViewModel without going down a rabbit hole -- needless to say it has a property References of type ObservableCollection<Reference> where Reference is defined earlier in this post.

ReferencedItem.xaml:

<v:BaseUserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</v:BaseUserControl.Resources>
<StackPanel Orientation="Horizontal">
    <Image x:Name="LinkIcon" Visibility="{Binding HasReference, Converter={StaticResource BooleanToVisibilityConverter}}" ToolTip="View Referenced Item" Source="/Images/link.png" Height="18" MouseUp="LinkIcon_MouseUp"/>
    <TextBlock x:Name="ReferencedObjectDesc" Text="{Binding ReferenceHierarchy}" FontStyle="Italic" VerticalAlignment="Center" />
</StackPanel>

I just wanted to post the answer (explanation) I came across.

The problem was changing the DataContext of my ReferencedItem user control in the constructor. The view would instantiate a ReferencedItem and alter the DataContext - so once it was time to bind I had already flipped the context from the intended Reference .

There are multiple ways to resolve the timing - all project dependent. Either avoid setting the DataContext all together, set it post binding, or change the context on other items as appropriate.

Much thanks to Sinatr , Andrew Stephens , and Mike Strobel for all mentioning this at one point or another -- just took me some time to actually reach it. I don't think there's a way to assign credit to a comment, but let me know if there is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM