将IList绑定到DependencyProperty

时间:2012-09-12 19:36:29

标签: c# xaml dependency-properties

我使用自己的DependencyProperty ItemsSource创建了我自己的自定义控件。它根据绑定列表中提供的项目数量动态创建按钮。创建XAML时,我应该能够通过声明

将列表绑定到我的自定义控件
ItemsSource="{Binding ListOfData}". 

我似乎无法显示按钮或显示,数据是否未正确绑定到列表?


         [TemplateVisualState(GroupName = "Button0States", Name = "Button0Visible")]
         [TemplateVisualState(GroupName = "Button0States", Name = "Button0NotVisible")]
         [TemplateVisualState(GroupName = "Button1States", Name = "Button1Visible")]
         [TemplateVisualState(GroupName = "Button1States", Name = "Button1NotVisible")]
         [TemplateVisualState(GroupName = "Button2States", Name = "Button2Visible")]
         [TemplateVisualState(GroupName = "Button2States", Name = "Button2NotVisible")]
         [TemplateVisualState(GroupName = "Button3States", Name = "Button3Visible")]
         [TemplateVisualState(GroupName = "Button3States", Name = "Button3NotVisible")]
         [TemplateVisualState(GroupName = "Button4States", Name = "Button4Visible")]
         [TemplateVisualState(GroupName = "Button4States", Name = "Button4NotVisible")]
         [TemplateVisualState(GroupName = "Button5States", Name = "Button5Visible")]
         [TemplateVisualState(GroupName = "Button5States", Name = "Button5NotVisible")]
         [TemplateVisualState(GroupName = "Button6States", Name = "Button6Visible")]
         [TemplateVisualState(GroupName = "Button6States", Name = "Button6NotVisible")]
         [TemplateVisualState(GroupName = "Button7States", Name = "Button7Visible")]
         [TemplateVisualState(GroupName = "Button7States", Name = "Button7NotVisible")]
         [TemplatePart(Name = "btn0", Type = typeof(Control))]
         [TemplatePart(Name = "btn7", Type = typeof(Control))]
         [TemplatePart(Name = "btnMore", Type = typeof(Control))]
         [TemplateVisualState(GroupName = "MoreButtonStates", Name = "MoreButtonVisible")]
         [TemplateVisualState(GroupName = "MoreButtonStates", Name = "MoreButtonNotVisible")]
         public class FourByTwoGrid : Control
         {



        public FourByTwoGrid()
        {
            this.DefaultStyleKey = typeof(FourByTwoGrid);

            this.Loaded += new RoutedEventHandler(FourByTwoGrid_Loaded); 
            this.GotFocus += new RoutedEventHandler(FourByTwoGrid_GotFocus);
        }

        public IList ItemsSource
        {
            get {  return GetValue(ItemsSourceProperty) as IList; }
            set { Logger.Log("Value set"); SetValue(ItemsSourceProperty, value); }
        }

        /// <summary>
        /// Identifies the ItemsSource dependency property.
        /// </summary>
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register(
                "ItemsSource",
                typeof(IList),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null, OnItemsSourcePropertyChanged));

        /// <summary>
        /// ItemsSourceProperty property changed handler.
        /// </summary>
        /// <param name="d">FourByTwoGrid that changed its ItemsSource.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FourByTwoGrid source = d as FourByTwoGrid;          

            if (source != null)
            {
                source.AttemptToBuildGridUi();
            }
        }

   #region public DataTemplate ItemTemplate
        /// <summary>
        /// Gets or sets an ItemTemplate to be used in the buttons. 
        /// </summary>
        public DataTemplate ItemTemplate
        {
            get { return GetValue(ItemTemplateProperty) as DataTemplate; }
            set { SetValue(ItemTemplateProperty, value); }
        }

        /// <summary>
        /// Identifies the ItemTemplate dependency property.
        /// </summary>
        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register(
                "ItemTemplate",
                typeof(DataTemplate),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null, OnItemTemplatePropertyChanged));

        /// <summary>
        /// ItemTemplateProperty property changed handler.
        /// </summary>
        /// <param name="d">FourByTwoGrid that changed its ItemTemplate.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnItemTemplatePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FourByTwoGrid source = d as FourByTwoGrid;

            if (source != null)
            {
                source.AttemptToBuildGridUi();
            }
        }

        /// <summary>
        /// Update the visual state of buttons based on whether or not an item exists. 
        /// </summary>
        private void UpdateVisualState()
        {
            // set buttons to visible if there's a corresponding item
            var lastI = 0;

            if (ItemsSource != null)
            {
                for (int i = 0; i < ItemsSource.Count && i < 8; i++)
                {
                    lastI = i;
                    VisualStateManager.GoToState(this, "Button" + i + "Visible", false);
                    Logger.Log("Visible" + i);
                }
                lastI++;
            }


            // set buttons to nto visible for all buttons that don't have a corresponding item
           for (int i = lastI; i < 8; i++)
            {
            }

            if (ShouldMoreButtonBeVisible)
            {
                VisualStateManager.GoToState(this, "MoreButtonVisible", false);
            }
            else
            {
                VisualStateManager.GoToState(this, "MoreButtonNotVisible", false);
            }
        }

        /// <summary>
        /// Attempt to populate the UI based on control properties. 
        /// </summary>
        private void AttemptToBuildGridUi()
        {
            UpdateVisualState();

            UpdateItemsSourceBindings();
        }

        /// <summary>
        /// It seems that the TemplateParent bindings aren't automatically updated. 
        /// We'll invoke Update on each of these. 
        /// </summary>
        private void UpdateItemsSourceBindings()
        {

            if (ItemsSource == null)
                return;

            if ((ItemsSource.Count > 0) && !ItemsSource[0].Equals(Item0))
                Item0 = ItemsSource[0];

            if ((ItemsSource.Count > 1) && !ItemsSource[1].Equals(Item1))
                Item1 = ItemsSource[1];

            if ((ItemsSource.Count > 2) && !ItemsSource[2].Equals(Item2))
                Item2 = ItemsSource[2];

            if ((ItemsSource.Count > 3) && !ItemsSource[3].Equals(Item3))
                Item3 = ItemsSource[3];

            if ((ItemsSource.Count > 4) && !ItemsSource[4].Equals(Item4))
                Item4 = ItemsSource[4];

            if ((ItemsSource.Count > 5) && !ItemsSource[5].Equals(Item5))
                Item5 = ItemsSource[5];

            if ((ItemsSource.Count > 6) && !ItemsSource[6].Equals(Item6))
                Item6 = ItemsSource[6];

            if ((ItemsSource.Count > 7) && !ItemsSource[7].Equals(Item7))
                Item7 = ItemsSource[7];

            Logger.Log("Layout updated");
            ItemsCountText = ItemsSource.Count.ToString(CultureInfo.InvariantCulture);
        }

#region public object Item0
        /// <summary>
        /// Gets or sets item #0.
        /// </summary>
        public object Item0
        {
            get { return GetValue(Item0Property) as object; }
            set { SetValue(Item0Property, value); }
        }

        /// <summary>
        /// Identifies the Item0 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item0Property =
            DependencyProperty.Register(
                "Item0",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item0

        #region public object Item1
        /// <summary>
        /// Gets or sets item #1.
        /// </summary>
        public object Item1
        {
            get { return GetValue(Item1Property) as object; }
            set { SetValue(Item1Property, value); }
        }

        /// <summary>
        /// Identifies the Item1 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item1Property =
            DependencyProperty.Register(
                "Item1",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item1

        #region public object Item2
        /// <summary>
        /// Gets or sets item #2.
        /// </summary>
        public object Item2
        {
            get { return GetValue(Item2Property) as object; }
            set { SetValue(Item2Property, value); }
        }

        /// <summary>
        /// Identifies the Item2 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item2Property =
            DependencyProperty.Register(
                "Item2",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item2

        #region public object Item3
        /// <summary>
        /// Gets or sets item #3.
        /// </summary>
        public object Item3
        {
            get { return GetValue(Item3Property) as object; }
            set { SetValue(Item3Property, value); }
        }

        /// <summary>
        /// Identifies the Item3 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item3Property =
            DependencyProperty.Register(
                "Item3",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item3

        #region public object Item4
        /// <summary>
        /// Gets or sets item #4.
        /// </summary>
        public object Item4
        {
            get { return GetValue(Item4Property) as object; }
            set { SetValue(Item4Property, value); }
        }

        /// <summary>
        /// Identifies the Item4 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item4Property =
            DependencyProperty.Register(
                "Item4",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item4

        #region public object Item5
        /// <summary>
        /// Gets or sets item #5.
        /// </summary>
        public object Item5
        {
            get { return GetValue(Item5Property) as object; }
            set { SetValue(Item5Property, value); }
        }

        /// <summary>
        /// Identifies the Item5 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item5Property =
            DependencyProperty.Register(
                "Item5",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item5

        #region public object Item6
        /// <summary>
        /// Gets or sets item #6.
        /// </summary>
        public object Item6
        {
            get { return GetValue(Item6Property) as object; }
            set { SetValue(Item6Property, value); }
        }

        /// <summary>
        /// Identifies the Item6 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item6Property =
            DependencyProperty.Register(
                "Item6",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item6

        #region public object Item7
        /// <summary>
        /// Gets or sets item #7.
        /// </summary>
        public object Item7
        {
            get { return GetValue(Item7Property) as object; }
            set { SetValue(Item7Property, value); }
        }

        /// <summary>
        /// Identifies the Item7 dependency property.
        /// </summary>
        public static readonly DependencyProperty Item7Property =
            DependencyProperty.Register(
                "Item7",
                typeof(object),
                typeof(FourByTwoGrid),
                new PropertyMetadata(null));

        #endregion public object Item7

EpisodeList是SeriesViewModel类中的IList,我想将该列表绑定到我的EpisodeGrid控件。

public class SeriesViewModel : CoreViewModel
{
     public IList episodeList = new ObservableCollection<Episode>
     {
         new Episode {image =""},

         new Episode {image =""},
         ......
     }


    public IList EpisodeList
    {
        get {return this.episodeList;}
        set
        {
            this.episodeList = value;
            RaisePropertyChanged("EpisodeList");
        }
    }
 }

<Core:CoreView
xmlns:Core="clr-namespace:AmebaTV_XBOXApplication.ViewModel"
x:Class="AmebaTV_XBOXApplication.UI.EpisodeGridView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:GridLayout="clr-namespace:AmebaTV_XBOXApplication.Controls.GridLayout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xbox="clr-namespace:Microsoft.Xbox.Controls;assembly=Microsoft.Xbox"
mc:Ignorable="d"
d:DesignHeight="720" d:DesignWidth="1280"
Title="EpisodeGridView Page">

<Core:CoreView.ViewModel>
    <Binding Path="SeriesViewModel" Source="{StaticResource viewModelLocator}"/>
</Core:CoreView.ViewModel>

<Core:CoreView.Resources>
    <DataTemplate x:Key="button_template">
        <Button Width="50" Height="50" >
            <TextBlock Text="Button"/>
        </Button>
    </DataTemplate>
</Core:CoreView.Resources>

  <Grid x:Name="LayoutRoot"  Margin="0">         
    <GridLayout:FourByTwoGrid x:Name="fourbytwogrid"
              ItemsSource="{Binding EpisodeList}"
              ItemTemplate="{StaticResource button_template}"/>

  </Grid>
</Core:CoreView>

上面我错过了什么?它编译得很好,但在运行时EpisodeList不绑定。

2 个答案:

答案 0 :(得分:1)

我查看了代码,看起来确实很好。

如果在OnItemsSourcePropertyChanged方法中设置断点,则可以看到DP ItemsSourceProperty绑定到EpisodeList,并且存储在属性ItemsSource中的获取IList的调用具有我们期望的值。< / p>

有什么证据表明EpisodeList没有绑定到ItemsSource?

如果问题是网格按钮没有显示,我不确定你是否已经显示了如何创建按钮控件的任何代码,可能问题就在那里,而不是在绑定中。

这是我编写的ControlTemplate的一个示例,它管理您在FourByTwoGrid类中定义的状态。您可以在XAML中添加以下内容以引用它。

    <GridLayout:FourByTwoGrid x:Name="fourbytwogrid"
      ItemsSource="{Binding EpisodeList}"
      ItemTemplate="{StaticResource butemp}"
      Template="{StaticResource FourByTwoGridTemplate}" />

这是ControlTemplate的定义。如果没有这个,您的代码无法知道如何在方法UpdateVisualState()中显示您引用的状态。

将其添加到CoreView XAML中的资源字典中:

                                        

<ControlTemplate x:Key="FourByTwoGridTemplate" TargetType="GridLayout:FourByTwoGrid">
        <Grid>
            <vsm:VisualStateManager.VisualStateGroups>
                <vsm:VisualStateGroup x:Name="Button0States">
                    <vsm:VisualState x:Name="Button0Visible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Button0">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </vsm:VisualState>
                    <vsm:VisualState x:Name="Button0NotVisible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Button0">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </vsm:VisualState>
                </vsm:VisualStateGroup>
                <vsm:VisualStateGroup x:Name="Button1States">
                    <vsm:VisualState x:Name="Button1Visible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Button1">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </vsm:VisualState>
                    <vsm:VisualState x:Name="Button1NotVisible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Button1">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </vsm:VisualState>
                </vsm:VisualStateGroup>
                <vsm:VisualStateGroup x:Name="Button2States">
                    <vsm:VisualState x:Name="Button2Visible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Button2">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </vsm:VisualState>
                    <vsm:VisualState x:Name="Button2NotVisible">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Button2">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </vsm:VisualState>
                </vsm:VisualStateGroup>

            </vsm:VisualStateManager.VisualStateGroups>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Button Grid.Row="0" Grid.Column="0" Name="Button0" Content="0" Visibility="Hidden" />
            <Button Grid.Row="0" Grid.Column="1" Name="Button1" Content="1" Visibility="Hidden" />
            <Button Grid.Row="1" Grid.Column="0" Name="Button2" Content="2" Visibility="Hidden" />
            <Button Grid.Row="1" Grid.Column="1" Name="Button3" Content="3" Visibility="Hidden" />
            <Button Grid.Row="2" Grid.Column="0" Name="Button4" Content="4" Visibility="Hidden" />
            <Button Grid.Row="2" Grid.Column="1" Name="Button5" Content="5" Visibility="Hidden" />
            <Button Grid.Row="3" Grid.Column="0" Name="Button6" Content="6" Visibility="Hidden" />
            <Button Grid.Row="3" Grid.Column="1" Name="Button7" Content="7" Visibility="Hidden" />
        </Grid>
</ControlTemplate>

答案 1 :(得分:0)

问题出现在ViewModel。您正在尝试将ItemsSource绑定到名为“EpisodeList”的属性。但是RaisePropertyChanged指的是非约束成员“episodeList”。