2014-12-05 57 views
0

我在WPF中比較新,我面臨一個問題。
我必須實現從數據庫(也是數據)獲取UI(xaml)的表單。 將在運行時創建的這些表單中的每一個都會有不同的控制。
儘管我不同意這種方法,但我必須遵循我的老闆方向。
問題在於驗證。
我們決定使用驗證規則來做到這一點。
所以我試圖用AgeRangeRule來實現基本的例子。WPF使用驗證規則動態加載xaml

<TextBox Name="textBox1" Width="50" FontSize="15" 
    Validation.ErrorTemplate="{StaticResource validationTemplate}" 
    Style="{StaticResource textBoxInError}" 
    Grid.Row="1" Grid.Column="1" Margin="2"> 
    <TextBox.Text> 
    <Binding Path="Age" Source="{StaticResource ods}" 
     UpdateSourceTrigger="PropertyChanged" > 
     <Binding.ValidationRules> 
     <c:AgeRangeRule Min="21" Max="130"/> 
     </Binding.ValidationRules> 
    </Binding> 
    </TextBox.Text> 
</TextBox> 

,我得到的錯誤,當我加載XAML是

Additional information: 'Cannot create unknown type '{clr-namespace:WpfDynamicTest1}AgeRangeRule'.' 

,並在這一行:

<c:AgeRangeRule Min="21" Max="130"/> 

注:C被定義爲:

xmlns:c="clr-namespace:WpfDynamicTest1" 

我該如何克服這個錯誤?
我遇到了類似的錯誤與ControlTemplate和樣式的錯誤,但我將它們移動到Application.xaml並解決了我的問題。
我可以做一些類似的參考嗎?

編輯:附加信息: 如何加載XAML:
的 「細胞」 的形式具有以下屬性:

Public Property FormId() As Integer 
    Get 
     Return miFormId 
    End Get 
    Set(ByVal value As Integer) 
     miFormId = value 
     FormCharacteristics(value) 
    End Set 
End Property 

Public Property UI() As String 
    Get 
     Return msUI 
    End Get 
    Set(ByVal value As String) 
     msUI = value 
     Dim rootObject As DependencyObject = XamlReader.Parse(value) 
     Me.Content = rootObject 
    End Set 
End Property 

所以,當我叫我做這個形式:

Dim winD As New winDynamic 
winD.FormId = 4 
winD.Show() 

FormCharacteristics填充了msUI和UI被加載。

+0

是否確定ValidationRule「AgeRangeRule」在名爲WpfDynamicTest1的名稱空間中正確定義? – Younes 2014-12-05 10:47:54

+0

是的,如果我沒有在運行時從數據庫加載xaml並且像往常一樣代碼正在工作 – Nianios 2014-12-05 10:50:34

回答

0

雖然不知道你是否通過下面的一些鏈接的搜索,但我希望他們可以對你有所幫助:

Compile/Execute XAML during program runtime

WPF – dynamically compile and run event handlers within loose XAML using CodeDom

Loading XAML at runtime?

Error: 'Cannot create unknown type '{clr-namespace:NameSpace.Properties}Settings'.'

編輯

基於上面的鏈接,假設你使用XamlReader,我創建了一個樣本,其工作的罰款。在這種情況下,我發現的原因是,XAML解析器需要ParserContext來映射名稱空間以在運行時綁定所需的類型。

的Xaml(動態用戶控件來加載)

<UserControl 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Height="300" Width="300" 
     xmlns:c="clr-namespace:WpfApplication1"> 
    <UserControl.Resources> 
     <c:MyDataSource x:Key="ods"/> 

     <ControlTemplate x:Key="validationTemplate"> 
      <DockPanel> 
       <TextBlock Foreground="Red" FontSize="20">!</TextBlock> 
       <AdornedElementPlaceholder/> 
      </DockPanel> 
     </ControlTemplate> 
     <Style x:Key="textBoxInError" TargetType="{x:Type TextBox}"> 
      <Style.Triggers> 
       <Trigger Property="Validation.HasError" Value="true"> 
        <Setter Property="ToolTip" 
       Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
           Path=(Validation.Errors)[0].ErrorContent}"/> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </UserControl.Resources> 
    <StackPanel> 
     <TextBox Name="textBox1" Width="50" FontSize="15" 
     Validation.ErrorTemplate="{StaticResource validationTemplate}" 
     Style="{StaticResource textBoxInError}" 
     Grid.Row="1" Grid.Column="1" Margin="2"> 
      <TextBox.Text> 
       <Binding Path="Age" Source="{StaticResource ods}" 
      UpdateSourceTrigger="PropertyChanged" > 
        <Binding.ValidationRules> 
         <c:AgeRangeRule Min="21" Max="130"/> 
        </Binding.ValidationRules> 
       </Binding> 
      </TextBox.Text> 
     </TextBox> 

     <Button x:Name="btnDynamic" Width="150" Height="30" Content="Click Me"/> 
    </StackPanel> 
</UserControl> 

代碼後面(C#)

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      LoadXAML(); 
     } 

     public void LoadXAML() 
     { 
      try 
      { 
       using (StreamReader xamlStream = new StreamReader(@"C:\WpfApplication1\WpfApplication1\DynamicWindow.xaml")) 
       { 
        var context = new ParserContext(); 
        context.XamlTypeMapper = new XamlTypeMapper(new string[] { }); 
        context.XmlnsDictionary.Add("c", "clr-namespace:WpfApplication1"); 
        context.XamlTypeMapper.AddMappingProcessingInstruction("clr-namespace:WpfApplication1", "WpfApplication1", "WpfApplication1"); 

        string xamlString = xamlStream .ReadToEnd(); 

        DependencyObject rootObject = XamlReader.Parse(xamlString, context) as DependencyObject; 
        cntControl.Content = rootObject; //cntControl is a content control I placed inside MainWindow 
       } 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message.ToString()); 
      } 
     } 
    } 

對於綁定驗證,我使用的相同MSDN您提供的代碼。

此外,由於我現在沒有使用VB.NET HAT,所以我選擇C#作爲後面的代碼!儘管代碼很簡單。

+0

@Nianios如果更改:xmlns:c =「clr-namespace:WpfDynamicTest1」xmlns:c =「 clr-namespace:WpfDynamicTest1;程序集:WpfDynamicTest1OrWhatEverAssemblyItIsIn「 – 2014-12-05 11:00:39

+0

嗯,我在VB代碼,當我添加這個,我得到了很多錯誤。第一個是URI「clr-namespace:BindValidation; assembly:BindValidation」不是有效的名稱空間標識符。 – Nianios 2014-12-05 11:20:19

0

您的AngeRangeRule應該從ValidationRule派生。

public class AgeRangeRule : ValidationRule { .... }

而且你必須重寫ValidationResult成員:

public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) 
    { 
     // Cast value object and check if it is valid 
     return new ValidationResult(...,...); 
    } 
+0

這與問題無關。我跟着這個例子。所以我做了所有這些。現在我正試圖在運行時加載xaml。 – Nianios 2014-12-05 10:52:11

+0

奇怪。我的確嘗試過一個'AgeRangeRule'類,我得到了你的錯誤。當我從'ValidationRule'派生它並實現'Validate'時,你的代碼示例運行良好。 – Sjips 2014-12-05 11:06:11

+0

那麼你是說你在運行時加載xaml,它的工作原理?因爲我在運行時不加載xaml時運行良好,但在運行時加載它時沒有運行 – Nianios 2014-12-05 11:12:00