我有一个非常基本的视图,仅显示TextField:
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
TextField("Enter a string...", text: $viewModel.string)
}
}
Run Code Online (Sandbox Code Playgroud)
的TextField文本绑定到string视图模型上的属性:
class ViewModel: ObservableObject {
@Published var string: String = "" {
didSet {
print("didSet string:", string)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我添加了一个didSet属性观察器,以便在字符串更改时执行自定义操作。对于这个简单的例子,我只在控制台上打印一个字符串。
当我运行此代码并在文本字段中输入字符串“123”时,这是我得到的输出:
didSet string: 1
didSet string: 1
didSet string: 12
didSet string: 12
didSet string: 123
didSet string: 123
Run Code Online (Sandbox Code Playgroud)
为什么?
为什么didSet我输入的每个字符都会调用两次闭包?(我希望每个角色都会调用一次。)
代码有什么问题或者这是预期的行为吗?
binding textfield property-observer swiftui observableobject
我有一个对象,其中包含我想要绑定到表单元素的十几个字段,以便我可以使用该对象将数据发送回服务器进行保存.
我的容器对象的定义:
private static const emptyLink:Object = {
id: -1, title:'',
trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'',
linkTitle:'', linkBody:'',
answer1:'',answer2:'',answer3:'',answer4:'',answer5:''
};
[Bindable] public var currentLink:Object = emptyLink;
Run Code Online (Sandbox Code Playgroud)
currentLink在运行时分配给ArrayCollection中的特定索引,我只是使用该emptyLink对象进行初始化.
<mx:Panel id="triggerPanel" title="Trigger" width="33%">
<mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:TextInput id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" />
<mx:TextInput id="trigger2" width="100%" textAlign="left" text="{currentLink.trigger2}" />
<mx:TextInput id="trigger3" width="100%" textAlign="left" text="{currentLink.trigger3}" />
<mx:TextInput id="trigger4" width="100%" textAlign="left" text="{currentLink.trigger4}" />
<mx:TextInput id="trigger5" width="100%" textAlign="left" text="{currentLink.trigger5}" />
</mx:VBox>
</mx:Panel>
Run Code Online (Sandbox Code Playgroud)
当然,这编译并显示得很好,但每个实例都有运行时警告:
警告:无法绑定到类'Object'上的属性'trigger1'(类不是IEventDispatcher)警告:无法绑定到类'Object'上的属性'trigger2'(类不是IEventDispatcher)警告:无法绑定到类'Object'上的属性'trigger3'(类不是IEventDispatcher)警告:无法绑定到类'Object'上的属性'trigger4'(类不是IEventDispatcher)警告:无法在类上绑定属性'trigger5' '对象'(类不是IEventDispatcher)
并且在更改字段currentLink时不更新对象TextInput.
显而易见的答案是我的对象需要是实现的类的实例IEventDispatcher.答案没有告诉我的是实现该界面的细节(需要什么?什么不是?),以及是否有更简单的方法 …
在WPF中,我希望能够模板化默认情况下应用绑定的方式.
例如,我想写:
Text="{Binding Path=PedigreeName}"
Run Code Online (Sandbox Code Playgroud)
但就好像我打字了一样:
Text="{Binding Path=PedigreeName, Mode=TwoWay, UpdateSourceTrigger=LostFocus, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"
Run Code Online (Sandbox Code Playgroud)
任何的想法 ?
谢谢,
我想使用WPF ToggleButton来扩展和折叠我的应用程序中的一些控件.我如何使用XAML来实现这一目标?
我想,我可以在某种程度上绑定Visibility一些控件的属性到ToggleButton的IsChecked状态,但我不知道如何做到这一点.
也许我需要给我ToggleButton一个Name,然后使用绑定ElementName?然后我需要一个ValueConverter布尔值和可见性之间的转换,对吗?我怎么能ValueConverter为此目的制作通用的?
当我尝试将窗口的高度和宽度绑定到视图模型中的属性时,我遇到了一些问题.这是一个小样本应用程序来说明问题.这是app.xaml.xs中的代码
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow mainWindow = new MainWindow();
MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
mainWindow.DataContext = mainWindowViewModel;
mainWindow.Show();
}
}
Run Code Online (Sandbox Code Playgroud)
这是MainWindow.xaml:
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="{Binding WindowHeight}"
Width="{Binding WindowWidth}"
BorderThickness="{Binding WindowBorderThickness}">
</Window>
Run Code Online (Sandbox Code Playgroud)
这是视图模型:
public class MainWindowViewModel
{
public int WindowWidth { get { return 100; } }
public int WindowHeight { get { return 200; } }
public int WindowBorderThickness { get { return 8; } }
}
Run Code Online (Sandbox Code Playgroud)
程序启动时,会调用WindowHeight和WindowBorderThickness(但不是WindowWidth)的getter,因此窗口的高度和边框设置正确,但不是宽度. …
有趣的是,有时简单的事情会在后面咬我.
我可以使用像这样的DataGridTextColumn将DataGrid很好地绑定到某个任意类的Collection:
// bound to List<Class>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
Run Code Online (Sandbox Code Playgroud)
现在我想将DataGrid绑定到一个简单的String集合.因为没有属性"Name"或类似的东西要绑定,我该如何编写绑定:
// bound to List<String>
<DataGridTextColumn Header="Name" Binding="{Binding ???}"/>
Run Code Online (Sandbox Code Playgroud)
字符串没有属性"值"或类似的东西.如果我只是写{Binding},我将最终得到一个单向绑定,无法将更改写回Collection.
想一想,我认为不可能绑定到一个集合,所以我需要将我的字符串包装成一个类?
或者有办法吗?
如果控件B被隐藏,我想让Control A可见,反之亦然.现在我有这个转换器:
public class InvertVisibilityConverter : IValueConverter {
public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture) {
if (targetType == typeof(Visibility)) {
Visibility vis = (Visibility)value;
return vis == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
throw new InvalidOperationException("Converter can only convert to value of type Visibility.");
}
public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture) {
throw new Exception("Invalid call - one way only");
}
}
Run Code Online (Sandbox Code Playgroud)
而这个XAML:
<Button Visibility="{Binding ElementName=btn1, Path=Visibility, Converter={StaticResource InvertVisibilityConverter}}">Btn2</Button>
Run Code Online (Sandbox Code Playgroud)
哪个有效.我只是想知道在WPF/Silverlight中是否有更直接的方法来实现这一目标?我不介意有转换器,我只是想确保没有更好的方法我不知道.
我的WPF窗口中有一个TextBlock.
<TextBlock>
Some <Bold>formatted</Bold> text.
</TextBlock>
Run Code Online (Sandbox Code Playgroud)
渲染时它看起来像这样,
一些格式化文本.
我的问题是,我可以将此内联"内容"绑定到我的应用程序中的资源吗?
我得到了:
制作应用程序资源字符串,
myText="Some <Bold>formatted</Bold> text."
Run Code Online (Sandbox Code Playgroud)
和以下xaml(为简洁起见,省略了一些代码)
<Window xmlns:props="clr-namespace:MyApp.Properties">
<Window.Resources>
<props:Resources x:Key="Resources"/>
</Window.Resources>
<TextBlock x:Name="Try1"
Text="{Binding Source={StaticResource Resources} Path=myText}"/>
<TextBlock x:Name="Try2">
<Binding Source="{StaticResource Resources}" Path="myText" />
</TextBlock>
</Window>
Run Code Online (Sandbox Code Playgroud)
Try1呈现标签并且不影响格式.
一些<Bold>格式化的<Bold>文本.
Try2不会编译或渲染,因为资源"myText"不是Inline类型而是字符串.
这看似简单的任务是否可能,如果可行,怎么办?
我有一个ObservableCollection,我可以添加和删除集合中的项目.但我无法替换集合中的现有项目.有一种方法可以替换项目并将其反映在我的绑定组件上.
System.Collections.Specialized.NotifyCollectionChangedAction.Replace
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我如何做到这一点?
我正在尝试将一个集合绑定到ItemsControl,将Canvas作为items面板,并将每个项目的Canvas.Left和Top绑定到项目对象上的属性.基本上我正在尝试重新创建我在博客上的这篇文章中描述的二维数据绑定,但这次是在WinRT而不是WPF.
由于ItemsControl将您的ItemTemplate内容包装在另一个UI元素(在WinRT的情况下为ContentPresenter)中,并且它是直接放置在items面板中的那些包装器/容器元素,因此必须在这些容器上设置Left和Top; 你不能只在DataTemplate中设置它们.在WPF中,使用ItemContainerStyle中的绑定很容易做到这一点,例如:
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding Path=X}"/>
<Setter Property="Canvas.Top" Value="{Binding Path=Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)
但是当我在WinRT/XAML项目中尝试同样的事情时,我什么也得不到.甚至没有绑定错误.如果我对一个值进行硬编码,它就会起作用; 但是如果我使用绑定,则该属性将保持其默认值(零),并且"输出"窗口中不显示任何绑定错误.
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<!-- This works, so ItemContainerStyle does work in WinRT: -->
<Setter Property="Canvas.Left" Value="200"/>
<!-- But this silently fails, leaves Top as 0, and does not show
any binding errors in the debugger's Output window: -->
<Setter Property="Canvas.Top" Value="{Binding Y}"/>
</Style>
</ItemsControl.ItemContainerStyle>
Run Code Online (Sandbox Code Playgroud)
我已经验证了ContentPresenters确实有正确的DataContext(即集合项,而不是集合本身或其他时髦的东西),所以你认为这些绑定可以正常工作.但他们似乎甚至没有得到评估.如果我在其他地方放置了一个错误的绑定,并运行调试版本,我会在调试器的Output窗口中看到绑定错误; 但是如果我在ItemContainerStyle中引用了一个无意义的属性,则不会显示绑定错误.
这是一个更完整的例子,(据我所知)应该可以在WPF中正常工作,但是在WinRT中,所有内容都保留在原点:
<ItemsControl ItemsSource="{Binding Tiles}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style …Run Code Online (Sandbox Code Playgroud) binding itemscontrol itemcontainerstyle windows-runtime winrt-xaml
binding ×10
wpf ×7
xaml ×3
.net ×1
apache-flex ×1
c# ×1
data-binding ×1
datagrid ×1
default ×1
flex3 ×1
itemscontrol ×1
mxml ×1
replace ×1
resources ×1
silverlight ×1
swiftui ×1
templates ×1
textblock ×1
textfield ×1
togglebutton ×1
winrt-xaml ×1