我有一个用户控件,如下所示:
和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>
正如您在图片中看到的那样,只有子网字段填充了值,为什么绑定,例如start,end和gateway不起作用?我做错了什么
<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; }
}
}
Usercontrol 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 :(得分:1)
请先看一下这个答案:Hair loss and MVVM user controls
现在我复制并粘贴wpf usercontrols的一般答案
如果您使用依赖关系属性创建UserControl,那么您的绑定应始终包含某种&#34; 相对绑定&#34; - 我总是使用 elementname binding 。所以你的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 =&#34; {Binding ElementName = _parent}&#34;并且只需更改Binding to Start,其余由您决定
<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:当然你的地址属性ObjectType需要你在这里设置的公共属性:(例如,如果属性在你的Adresses对象中被称为MyStart那么......)
<range:IpRangeFields Start="{Binding MyStart}" End="{Binding End}"
Subnet="{Binding Subnet}" Gateway="{Binding Gateway}"/>
答案 1 :(得分:-1)
这是一个常见问题。
您正在使用UserControl
上的绑定,该绑定已经由其他内容设置DataContext
。
相反,您的绑定需要引用父控件DataContext,在本例中是ListBoxItem。
{Binding DataContext.Start,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=ListBoxItem}}