2015-05-29 61 views
0

我有一个用户控件,看起来像: enter image description here为什么绑定工作,只能由一个

和XAML代码:

<UserControl x:Class="Customizing.Views.IpRangeView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:ig="http://schemas.infragistics.com/xaml" 
      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
      xmlns:mvvm="http://www.galasoft.ch/mvvmlight" 
      xmlns:range="clr-namespace:Customizing.Views" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300" 
      DataContext="{Binding IpRangeVm, Source={StaticResource Locator}}"> 
    <Grid> 
     <ig:ThemeManager.Theme> 
      <ig:Office2013Theme StyleMicrosoftControls="True" /> 
     </ig:ThemeManager.Theme> 

     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 

     <TabControl Grid.Row="0" ItemsSource="{Binding Locations}"> 

      <TabControl.ItemTemplate> 
       <DataTemplate> 
        <Label Content="{Binding Name}" FontSize="16" FontWeight="Bold" /> 
       </DataTemplate> 
      </TabControl.ItemTemplate> 

      <TabControl.ContentTemplate> 
       <DataTemplate> 
        <ScrollViewer VerticalScrollBarVisibility="Auto"> 
         <ItemsControl ItemsSource="{Binding Addresses}"> 
          <ItemsControl.ItemsPanel> 
           <ItemsPanelTemplate> 
            <UniformGrid Columns="2" /> 
           </ItemsPanelTemplate> 
          </ItemsControl.ItemsPanel> 
          <ItemsControl.ItemTemplate> 
           <DataTemplate> 
            <Border Margin="20,15,20,15" Padding="15,20,15,20"> 
             <range:IpRangeFields Start="{Binding Start}" End="{Binding End}" 
                  Subnet="{Binding Subnet}" Gateway="{Binding Gateway}"> 
              <i:Interaction.Triggers> 
               <i:EventTrigger EventName="Error"> 
                <mvvm:EventToCommand Command="{Binding Path=DataContext.ErrorCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}}" /> 
               </i:EventTrigger> 
              </i:Interaction.Triggers> 
             </range:IpRangeFields> 
            </Border> 
           </DataTemplate> 
          </ItemsControl.ItemTemplate> 
         </ItemsControl> 
        </ScrollViewer> 
       </DataTemplate> 

      </TabControl.ContentTemplate> 
     </TabControl> 

    </Grid> 
</UserControl> 

正如你可以在图片中看到,只有子网字段填入值,为什么与绑定,例如开始,结束和网关不起作用?我在做什么错

<range:IpRangeFields Start="{Binding Start}" End="{Binding End}" 
        Subnet="{Binding Subnet}" Gateway="{Binding Gateway}"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Error"> 
      <mvvm:EventToCommand Command="{Binding Path=DataContext.ErrorCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
</range:IpRangeFields> 

和视图模型和视图绑定到:

using System.Collections.ObjectModel; 
using System.Diagnostics; 
using Customizing.Models; 
using Customizing.Services; 
using GalaSoft.MvvmLight; 
using GalaSoft.MvvmLight.Command; 

namespace Customizing.ViewModel 
{ 
    public class IpRangeViewModel : ViewModelBase 
    { 
     private readonly IDataService _dataService; 

     public IpRangeViewModel(IDataService dataService) 
     { 
      _dataService = dataService; 
      _dataService.QueryIpRanges((ranges, error) => { Locations = ranges; }); 

      ErrorCmd = new RelayCommand(() => { Debug.WriteLine("Error occurs"); }); 
     } 

     public ObservableCollection<LocationRange> Locations { get; set; } 
     public RelayCommand ErrorCmd { get; set; } 
    } 
} 

和模型

using System.Collections.ObjectModel; 

namespace Customizing.Models 
{ 
    public class LocationRange 
    { 
     public string Name { get; set; } 
     public ObservableCollection<IpRange> Addresses { get; set; } 
    } 
} 

用户控件iprangefield:

<UserControl x:Class="Customizing.Views.IpRangeFields" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:ig="http://schemas.infragistics.com/xaml" 
      xmlns:local="clr-namespace:Customizing.Views" 
      xmlns:net="clr-namespace:System.Net;assembly=System" 
      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
      xmlns:behaviors="clr-namespace:Customizing.Behaviors" 
      xmlns:system="clr-namespace:System;assembly=mscorlib" 
      mc:Ignorable="d" 
      x:Name="_parent" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <UserControl.Resources> 
     <system:String x:Key="InputMaskIp">000.000.000.000</system:String> 
    </UserControl.Resources> 
    <Grid DataContext="{Binding ElementName=_parent}"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="60" /> 
      <RowDefinition Height="10" /> 
      <RowDefinition Height="60" /> 
      <RowDefinition Height="10" /> 
      <RowDefinition Height="60" /> 
      <RowDefinition Height="10" /> 
      <RowDefinition Height="60" /> 
      <RowDefinition Height="10" /> 
     </Grid.RowDefinitions> 

     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition Width="2.5*" /> 
     </Grid.ColumnDefinitions> 

     <Label Grid.Row="0" Grid.Column="0" Content="Start" VerticalContentAlignment="Center" FontSize="18" 
       HorizontalContentAlignment="Center" FontWeight="Bold" /> 
     <Label Grid.Row="2" Grid.Column="0" Content="End" VerticalContentAlignment="Center" FontSize="18" 
       HorizontalContentAlignment="Center" FontWeight="Bold" /> 
     <Label Grid.Row="4" Grid.Column="0" Content="Subnet" VerticalContentAlignment="Center" FontSize="18" 
       HorizontalContentAlignment="Center" FontWeight="Bold" /> 
     <Label Grid.Row="6" Grid.Column="0" Content="Gateway" VerticalContentAlignment="Center" FontSize="18" 
       HorizontalContentAlignment="Center" FontWeight="Bold" /> 

     <TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="0" Grid.Column="1" 
       FontSize="22" Validation.Error="_ValidationError"> 
      <Binding Path="Start" ValidatesOnNotifyDataErrors="True" UpdateSourceTrigger="PropertyChanged" 
        NotifyOnValidationError="true"> 
       <Binding.ValidationRules> 
        <local:IpAddressRule /> 
       </Binding.ValidationRules> 
      </Binding> 
      <i:Interaction.Behaviors> 
       <behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" /> 
      </i:Interaction.Behaviors> 
     </TextBox> 

     <TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="2" Grid.Column="1" 
       FontSize="22" Validation.Error="_ValidationError"> 
      <Binding Path="End" ValidatesOnNotifyDataErrors="True" UpdateSourceTrigger="PropertyChanged" 
        NotifyOnValidationError="true"> 
       <Binding.ValidationRules> 
        <local:IpAddressRule /> 
       </Binding.ValidationRules> 
      </Binding> 
      <i:Interaction.Behaviors> 
       <behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" /> 
      </i:Interaction.Behaviors> 
     </TextBox> 

     <TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="4" Grid.Column="1" 
       FontSize="22" Validation.Error="_ValidationError"> 
      <Binding Path="Subnet" ValidatesOnNotifyDataErrors="True" UpdateSourceTrigger="PropertyChanged" 
        NotifyOnValidationError="true"> 
       <Binding.ValidationRules> 
        <local:IpAddressRule /> 
       </Binding.ValidationRules> 
      </Binding> 
      <i:Interaction.Behaviors> 
       <behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" /> 
      </i:Interaction.Behaviors> 
     </TextBox> 

     <TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="6" Grid.Column="1" 
       FontSize="22" Validation.Error="_ValidationError"> 
      <Binding Path="Gateway" ValidatesOnNotifyDataErrors="True" UpdateSourceTrigger="PropertyChanged" 
        NotifyOnValidationError="true"> 
       <Binding.ValidationRules> 
        <local:IpAddressRule /> 
       </Binding.ValidationRules> 
      </Binding> 
      <i:Interaction.Behaviors> 
       <behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" /> 
      </i:Interaction.Behaviors> 
     </TextBox> 


    </Grid> 
</UserControl> 

和后面的代码:

using System; 
using System.Diagnostics; 
using System.Globalization; 
using System.Net; 
using System.Windows; 
using System.Windows.Controls; 

namespace Customizing.Views 
{ 
    /// <summary> 
    ///  Interaction logic for IpRangeFields.xaml 
    /// </summary> 
    public partial class IpRangeFields : UserControl 
    { 
     public static readonly DependencyProperty StartProperty = DependencyProperty.Register("Start", typeof (string), 
      typeof (IpRangeFields), new PropertyMetadata(null)); 

     public static readonly DependencyProperty EndProperty = DependencyProperty.Register("End", typeof (string), 
      typeof (IpRangeFields), new PropertyMetadata(null)); 

     public static readonly DependencyProperty SubnetProperty = DependencyProperty.Register("Subnet", typeof (string), 
      typeof (IpRangeFields), new PropertyMetadata(null)); 

     public static readonly DependencyProperty GatewayProperty = DependencyProperty.Register("Gateway", 
      typeof (string), typeof (IpRangeFields), new PropertyMetadata(null)); 

     // Register the routed event 
     public static readonly RoutedEvent ErrorEvent = 
      EventManager.RegisterRoutedEvent("Error", RoutingStrategy.Bubble, 
      typeof(RoutedEventHandler), typeof(IpRangeFields)); 

     public IpRangeFields() 
     { 
      InitializeComponent(); 
     } 

     public event RoutedEventHandler Error 
     { 
      add { AddHandler(ErrorEvent, value); } 
      remove { RemoveHandler(ErrorEvent, value); } 
     } 

     public string Start 
     { 
      get { return (string) GetValue(StartProperty); } 
      set { SetValue(StartProperty, value); } 
     } 

     public string End 
     { 
      get { return (string) GetValue(EndProperty); } 
      set { SetValue(EndProperty, value); } 
     } 

     public string Subnet 
     { 
      get { return (string) GetValue(SubnetProperty); } 
      set { SetValue(SubnetProperty, value); } 
     } 

     public string Gateway 
     { 
      get { return (string) GetValue(GatewayProperty); } 
      set { SetValue(GatewayProperty, value); } 
     } 

     private void _ValidationError(object sender, ValidationErrorEventArgs e) 
     { 
      RaiseEvent(new RoutedEventArgs(ErrorEvent, sender)); 
     } 

    } 

    public class IpAddressRule : ValidationRule 
    { 
     public override ValidationResult Validate(object value, CultureInfo cultureInfo) 
     { 
      IPAddress ip; 
      if (!IPAddress.TryParse(value.ToString(), out ip)) 
      { 
       return new ValidationResult(false, "IP address is not valid."); 
      } 

      return new ValidationResult(true, null); 
     } 
    } 
} 
+0

您可以粘贴该控件绑定的ViewModel吗? – Baldrick

+0

你也可以粘贴'LocationRange'和Adresses的代码,因为这是绑定的属性? – Kryptos

+0

我粘贴了代码。 –

回答

-1

这是一个常见问题。

您正在使用UserControl上的绑定,其中已有其他设置的DataContext

相反,您的绑定需要引用父控件DataContext,在这种情况下是ListBoxItem。

{Binding DataContext.Start, 
      RelativeSource={RelativeSource Mode=FindAncestor, 
             AncestorType=ListBoxItem}} 
1

请看到这个答案第一:Hair loss and MVVM user controls

,现在我的副本,如果你创建然后依赖属性一个用户控件粘贴到WPF用户控件

笼统的回答你的绑定应始终包含一些种类“相对绑定” - 我总是使用elementname绑定。所以你的usercontrol绑定应该看起来像这样。

<UserControl x:Name="uc"> 
<StackPanel Orientation="Horizontal"> 
    <Image Source="{Binding Source={x:Static helper:ImageHelper.JumpLabelImage}}" Width="16" Height="16" VerticalAlignment="Center"/> 
    <TextBlock > 
    <Hyperlink Command="{Binding ElementName=uc, Path=JumpCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
       CommandParameter="{Binding ElementName=uc, Path=CommandParameter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" > 
     <TextBlock Text="{Binding ElementName=uc, Path=LabelText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" VerticalAlignment="Center" /> 
    </Hyperlink> 
    </TextBlock> 
</StackPanel> 
</UserControl> 

如果你为你的usercontrol设置datacontext为self,那么你破坏了datacontext继承,这不是你想要的。所以你必须在你的用户控件中删除各种将datacontext设置为self的类型。

编辑:更改您的代码在IpRangeFields:没有DataContext !!!的DataContext =“{绑定的ElementName = _parent}”,只是改变绑定启动剩下的就是给你

<UserControl x:Class="Customizing.Views.IpRangeFields" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:ig="http://schemas.infragistics.com/xaml" 
     xmlns:local="clr-namespace:Customizing.Views" 
     xmlns:net="clr-namespace:System.Net;assembly=System" 
     xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
     xmlns:behaviors="clr-namespace:Customizing.Behaviors" 
     xmlns:system="clr-namespace:System;assembly=mscorlib" 
     mc:Ignorable="d" 
     x:Name="Uc" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<UserControl.Resources> 
    <system:String x:Key="InputMaskIp">000.000.000.000</system:String> 
</UserControl.Resources> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="60" /> 
     <RowDefinition Height="10" /> 
     <RowDefinition Height="60" /> 
     <RowDefinition Height="10" /> 
     <RowDefinition Height="60" /> 
     <RowDefinition Height="10" /> 
     <RowDefinition Height="60" /> 
     <RowDefinition Height="10" /> 
    </Grid.RowDefinitions> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*" /> 
     <ColumnDefinition Width="2.5*" /> 
    </Grid.ColumnDefinitions> 

    <Label Grid.Row="0" Grid.Column="0" Content="Start" VerticalContentAlignment="Center" FontSize="18" 
      HorizontalContentAlignment="Center" FontWeight="Bold" /> 

    <TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="0" Grid.Column="1" 
      FontSize="22" Validation.Error="_ValidationError" 
      Text="{Binding ElementName=Uc, Path=Start, ValidatesOnNotifyDataErrors=True, UpdateSourceTrigger=PropertyChanged}"> 
     </TextBox> 

</Grid> 
</UserControl> 

EDIT2:当然还有你的地址属性对象类型需要您在此处设置的公共属性:(例如。如果该属性将在您的Adresses对象中被称为MyStart,则..)

<range:IpRangeFields Start="{Binding MyStart}" End="{Binding End}" 
        Subnet="{Binding Subnet}" Gateway="{Binding Gateway}"/> 
+0

“在绑定到DP时始终使用相对绑定”...您能对此进行精心设计吗? – Fredrik

+0

这与OP有什么关系?唯一的viewmodel设置在正确的视图上。其他一切都只是属性。 – Kryptos

+1

当你创建一个“真实”的用户控件,那么你创建你的用户控件的至少一个的DependencyProperty。因此,如果我在用户控件创建DP像“MYTEXT”,那么我要创建像的结合<文本框的文本=“{结合的ElementName = UC,路径= MYTEXT}” />在我UserControl.xaml。现在究竟在哪儿我想使用这个控制,我不得不这样做:<本地:的MyUserControl MYTEXT =“{结合MyViewmodelProperty}” /> – blindmeis

相关问题