Я относительно новичок в WPF, и у меня возникла проблема.
Я должен реализовать форму, которая получает UI (xaml) из базы данных (как и данные). Каждая из этих форм, которая будет создана во время выполнения, будет иметь разные элементы управления.
Хотя я не согласен с этим подходом, я должен следовать указаниям моего начальника.
Проблема заключается в проверке.
Мы решили сделать это с Правилами валидации.
Поэтому я попытался реализовать основной пример с помощью AgeRangeRule.
<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 и Style для ошибок, но я переместил их в 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.
Хотя не уверен, что вы просматриваете некоторые из следующих ссылок, но я надеюсь, что они могут вам помочь:
Компиляция/выполнение XAML во время выполнения программы
WPF - динамически компилирует и запускает обработчики событий в свободном XAML, используя CodeDom
Загрузка XAML во время выполнения?
Ошибка: "Невозможно создать неизвестный тип" {clr-namespace: NameSpace.Properties} Настройки '.'
РЕДАКТИРОВАТЬ
Основываясь на ссылках выше, если вы используете XamlReader, я создал образец и его работу. В этом случае причина, по которой я нашел, для XAML Parser нуждается в 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>
Код позади (С#)
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 сейчас, я выбираю С# для кода позади !! Хотя код достаточно прост.
Ваш 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(...,...);
}
AgeRangeRule
и я получил ошибку, которую вы имели. И когда я извлек его из ValidationRule
и реализовал Validate
, ваш пример кода работал нормально.