【问题标题】:How to Bind ItemsSource of ComboBox in ControlTemplate?如何在 ControlTemplate 中绑定 ComboBox 的 ItemsSource?
【发布时间】:2018-11-08 00:41:17
【问题描述】:

情况

我必须更改 GridView 中 Flyout 项的内容。所以我在Page.Resources 中创建ControlTemplate 并将其设置在ContentControl 中,它位于Flyout 中。

问题

我在ControlTemplate 中有一个ComboBox。现在我想将ComboBoxItemsSource 设置为List<string> (_easingType),它在MainPage 中声明

问题

如何在ControlTemplate 中绑定/设置ItemsSourceComboBox

代码

我已经删除了代码中不必要的部分

XAML

<Page.Resources>
    <ControlTemplate x:Key="BlurEditFlyout">
        ....
        <ComboBox ItemsSource="{Bind it to the _esaingType}" />
        ....
    <ControlTemplate x:Key="BlurEditFlyout">
</Page.Resources>

<GridView ItemsSource="{x:Bind _items}">
    <GridView.ItemTemplate>
        <DataTemplate x:DataType="local:MethodData">
            <StackPanel>
                ....
                <Button Visibility="{x:Bind EditButtonVisibility}">
                    <Button.Flyout>
                        <Flyout>
                            <Flyout.FlyoutPresenterStyle>
                                <Style TargetType="FlyoutPresenter">
                                    <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
                                    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
                                </Style>
                            </Flyout.FlyoutPresenterStyle>
                            <ContentControl Template="{x:Bind FlyoutTemplate}"/>
                        </Flyout>
                    </Button.Flyout>
                    <SymbolIcon Symbol="Edit"/>
                </Button>
                ....
            </StackPanel>
        </DataTemplate>
    </GridView.ItemTemplate>
</GridView>

代码背后

public sealed partial class MainPage : Page
{

    ObservableCollection<MethodData> _items = new ObservableCollection<MethodData>();
    List<string> _easingType = new List<string>(Enum.GetNames(typeof(EasingType)).ToArray());
    Dictionary<MethodName, ControlTemplate> _buttonFlyoutDictionary = new Dictionary<MethodName, ControlTemplate>();

    public MainPage()
    {
        this.InitializeComponent();

        LoadFlyoutResources();

        _items.Add(GetMethodData(MethodName.Blur));
    }

    private void LoadFlyoutResources()
    {
        _buttonFlyoutDictionary.Add(MethodName.Blur, (ControlTemplate)Resources["BlurEditFlyout"]);
        .....
    }

    private MethodData GetMethodData(MethodName methodName)
    {
        _buttonFlyoutDictionary.TryGetValue(methodName, out ControlTemplate flyoutTemplate);
        return new MethodData(methodName, flyoutTemplate);
    }
}

public class MethodData
{
    public string Name { get; set; }
    public ControlTemplate FlyoutTemplate { get; set; }
    public Visibility EditButtonVisibility { get; set; }

    public MethodData(MethodName name, ControlTemplate flyoutTemplate)
    {
        Name = name.ToString();
        FlyoutTemplate = flyoutTemplate;
        EditButtonVisibility = (name == MethodName.Then) ? Visibility.Collapsed : Visibility.Visible;
    }
}

public enum MethodName
{
    Blur,
    ....
}

完整代码

AnimationSetSamplePage.zip

【问题讨论】:

  • 为什么这些字段是在 MainPage 类之外声明的?
  • 虽然您指出unnecessary parts of the code 已被删除,但您仍需要提供可用于重现问题的minimal reproducible example
  • @Nkosi 抱歉,粘贴代码时出错。我已经提供了一个简约的例子。 &lt;ComboBox ItemsSource="{Bind it to the _esaingType}" /&gt; 这一行解释了一切。
  • @Nkosi 这是我的完整代码。 dl.dropboxusercontent.com/s/xnefuqqurbq0jkj/…
  • @Nkosi 有更新吗?

标签: c# xaml uwp


【解决方案1】:

Flyout 控件中的 DataContext 实际上是“_items”中的每个项目。您需要创建一个 DataContext 代理来访问您的 Page 的 DataContext。您可以按照这两个链接中的任何一个链接来创建代理。

https://weblogs.asp.net/dwahlin/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls

http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/

它的要点是您需要创建一个可以作为静态资源引用的代理。在第一个链接之后,您将执行以下操作:

public class DataContextProxy : FrameworkElement
{
    public DataContextProxy()
    {
        this.Loaded += new RoutedEventHandler(DataContextProxy_Loaded);
    }

    void DataContextProxy_Loaded(object sender, RoutedEventArgs e)
    {
        Binding binding = new Binding();
        if (!String.IsNullOrEmpty(BindingPropertyName))
        {
            binding.Path = new PropertyPath(BindingPropertyName);
        }
        binding.Source = this.DataContext;
        binding.Mode = BindingMode;
        this.SetBinding(DataContextProxy.DataSourceProperty, binding);             
    }

    public Object DataSource
    {
        get { return (Object)GetValue(DataSourceProperty); }
        set { SetValue(DataSourceProperty, value); }
    }

    public static readonly DependencyProperty DataSourceProperty =
        DependencyProperty.Register("DataSource", typeof(Object), typeof(DataContextProxy), null);


    public string BindingPropertyName { get; set; }

    public BindingMode BindingMode { get; set; }

}

您应该为_easingType 使用public 访问修饰符

public List<string> _easingType = new List<string>(Enum.GetNames(typeof(EasingType)).ToArray());

在 MainPage.xaml 中

<Page.Resources>        
    <local:DataContextProxy x:Key="DataContextProxy" />
    <ControlTemplate x:Key="BlurEditFlyout">
        ....
        <ComboBox ItemsSource="{Binding Source={StaticResource DataContextProxy}, Path=DataSource._easingType}" />
        ....
    <ControlTemplate x:Key="BlurEditFlyout">
</Page.Resources>
...

【讨论】:

  • 我添加了更多代码来完善这个解决方案。随时恢复更改。
  • 不,没关系。
【解决方案2】:

如何在ControlTemplate中绑定/设置ComboBox的ItemsSource

我不确定你问这个问题是否有深刻的理由,但直接回答这个问题,我们可以将字符串列表_esaingType设置为DataContext属性的值并绑定它。例如:

XAML

<Page.Resources>
    <ControlTemplate TargetType="FlyoutPresenter"  x:Key="BlurEditFlyout" >
      ...                   
                <ComboBox ItemsSource="{Binding}" />
      ...
    </ControlTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
    <Button>
        <Button.Flyout>
            <Flyout>
                <Flyout.FlyoutPresenterStyle>
                    <Style TargetType="FlyoutPresenter">
                        <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Disabled" />
                        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
                        <Setter Property="Template" Value="{StaticResource BlurEditFlyout}">                                
                        </Setter>
                    </Style>
                </Flyout.FlyoutPresenterStyle>
                <!--<ContentControl Template="{StaticResource BlurEditFlyout}"/>-->
            </Flyout>
        </Button.Flyout>
        <SymbolIcon Symbol="Edit"/>
    </Button> 
</Grid>

后面的代码

List<string> _easingType = new List<string>();  
public MainPage()
{
   this.InitializeComponent();
   _easingType.Add("test2");
   _easingType.Add("test1");
   this.DataContext = _easingType;
}

对此方式有任何疑虑或在您身边使用时有任何问题,请告诉我,我会及时跟进。更多详情请参考Data binding in depth

【讨论】:

  • 它不工作。我想这是因为我的FlyoutItemTemplateGridView 里面
猜你喜欢
  • 2013-01-14
  • 1970-01-01
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 2018-08-02
相关资源
最近更新 更多