2015-10-21 66 views
0

不確定這是否可能。我有一個可觀察的集合「OptionsList」,其中包含具有「Name」和「IsEnabled」屬性的簡單對象。從XAML中的明確枚舉綁定到父項的屬性

即使世界看起來像

Configuration 
    |--Option1 
    |--Option2 
    |--Option3 
     |--Enabled 

第一子菜單的菜單「選項1,選項2,選項3」正確但隨後結合來自內部的我嘗試從第一子菜單中訪問這些項目,並結合其數據上下文,但我似乎無法通過RelativeSource訪問它們出於某種原因。

<MenuItem Header="Configuration"> 
    <MenuItem Header="Service" ItemsSource="{Binding OptionsList}"> 
    <MenuItem.ItemContainerStyle> 
     <Style TargetType="MenuItem"> 
     <Setter Property="Header" Value="{Binding Name}"/> 
     <Setter Property="ItemsSource"> 
      <Setter.Value> 
      <x:Array Type="MenuItem"> 
       <MenuItem Header="Enabled" IsCheckable="True" 
         DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}, Path=DataContext}" 
         IsChecked="{Binding Path=IsEnabled}"/> 
      </x:Array> 
      </Setter.Value> 
     </Setter> 
     </Style> 
    </MenuItem.ItemContainerStyle> 
    </MenuItem> 
</MenuItem> 

回答

1

IsChecked與錯誤的路徑綁定。這裏隱含的Binding源已經是DataContext,它綁定到父MenuItem的DataContext。因此,路徑DataContext.IsEnabled - 它實際上會尋找DataContext.DataContext.IsEnabled - 當然這是無法解決的。

你可以簡單地刪除DataContext.

IsChecked="{Binding IsEnabled}" 

的另一個問題是DataContext會自動流下子菜單項,所以你不需要設置DataContext爲內部的MenuItems,這實際上不工作(我已經嘗試過了,不知何故RelativeSource約束力不工作 - 它不是某種斷開的可視化樹 - 因爲在DataContext被向下流動OK - 所以它是非常奇怪在這種情況下):

<MenuItem Header="Enabled" IsCheckable="True" IsChecked="{Binding IsEnabled}"/> 

這是一個更安全的方法,我們使用HierarchicalDataTemplate。請注意,ItemsSource被設置爲1個元素的虛擬數組。在ItemTemplate裏面我們將使用綁定步行到父元素爲IsChecked財產

<MenuItem Header="Service" ItemsSource="{Binding OptionsList}"> 
    <MenuItem.ItemContainerStyle> 
     <Style TargetType="MenuItem"> 
      <Setter Property="ItemTemplate"> 
       <Setter.Value> 
        <HierarchicalDataTemplate> 
        <HierarchicalDataTemplate.ItemsSource> 
         <x:Array Type="{x:Type sys:Int32}"> 
          <sys:Int32>0</sys:Int32> 
         </x:Array> 
        </HierarchicalDataTemplate.ItemsSource> 
        <HierarchicalDataTemplate.ItemTemplate> 
          <DataTemplate> 
           <TextBlock Text="Enabled"/> 
          </DataTemplate> 
        </HierarchicalDataTemplate.ItemTemplate> 
        <HierarchicalDataTemplate.ItemContainerStyle> 
         <Style TargetType="MenuItem"> 
          <Setter Property="IsCheckable" Value="True"/> 
          <Setter Property="IsChecked" 
            Value="{Binding DataContext.IsEnabled, RelativeSource={RelativeSource AncestorType=MenuItem}}"/> 
         </Style> 
        </HierarchicalDataTemplate.ItemContainerStyle> 
        <TextBlock Text="{Binding Name}"/>      
        </HierarchicalDataTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </MenuItem.ItemContainerStyle> 
+0

我試過但仍然沒有成功。我更新了我的示例以反映您的更改。雖然 – bgura

+0

@Thatoneguy看到我的編輯,問題是你顯式設置'DataContext'基於'RelativeSource'綁定 - ***失敗***(這種情況很奇怪,因爲通常如果'RelativeSource'綁定失敗, DataContext不會流下來,但是在這種情況下,它不會流下來)。 –

+1

@解決問題可能不是綁定不起作用。更重要的是,它只能工作一次,即使在您提出的更正中。例如。如果有2個選項,你會看到他們兩個,你可以切換它們。但是,當你打開選項一個子菜單,然後打開選項二,然後回到選項一,啓用菜單不會顯示任何文本,並將不再工作... –

1

我認爲該項目顯示不會因爲在WPF一些實物的MenuItems的再利用(不知道這是否一起工作是MenuItem中的一個錯誤)。玩x:Shared="False"沒有修復它。

有一種不同的方法來實現自己的目標:

  1. 創建一個助手類,它是你的期權類的子類,並提供該助手成爲選項的孩子的一個實例。
  2. 綁定在XAML這個輔助類

下面是一些代碼,詳細顯示了怎麼辦:

XAML:

<MenuItem Header="Service" ItemsSource="{Binding OptionsList}"> 
    <MenuItem.ItemContainerStyle> 
    <Style TargetType="MenuItem"> 
     <Setter Property="Header" Value="{Binding Name}" /> 
     <Setter Property="ItemsSource" Value="{Binding ToggleItem}" /> 
     <Setter Property="ItemContainerStyle"> 
     <Setter.Value> 
      <Style TargetType="MenuItem"> 
      <Setter Property="Header" Value="{Binding Name}" /> 
      <Setter Property="IsCheckable" Value="True" /> 
      <Setter Property="IsChecked" Value="{Binding IsEnabled}" /> 
      </Style> 
     </Setter.Value> 
     </Setter> 
    </Style> 
    </MenuItem.ItemContainerStyle> 
</MenuItem> 

C#

public class OptionHelper 
{ 
    private readonly Option owner; 

    public OptionHelper(Option owner) 
    { 
    this.owner = owner; 
    } 

    public bool IsEnabled 
    { 
    get { return this.owner.IsEnabled; } 
    set { this.owner.IsEnabled = value; } 
    } 
} 

public class Option : INotifyPropertyChanged 
{ 
    public ObservableCollection<OptionHelper> ToggleItem { get; private set; } 

    public Option(string name, bool isEnabled) 
    { 
    this.ToggleItem = new ObservableCollection<OptionHelper>() { new OptionHelper(this) }; 
    this.name = name; 
    this.isEnabled = isEnabled; 
    } 

    // your code here... 
} 

我知道這不是完美的解決方案,但它的工作原理......不知道是否有人在沒有幫手的情況下找到解決方案。

+0

這確實不是完美的,但這是我現在的工作方式。我做了「ToggleItem」只是一個選項列表,並作爲唯一的項目傳入「this」 – bgura