Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 在XAML中,如果函数是';的输入和输出绑定到不同的对象?_Wpf_Xaml_Binding_Timer - Fatal编程技术网

Wpf 在XAML中,如果函数是';的输入和输出绑定到不同的对象?

Wpf 在XAML中,如果函数是';的输入和输出绑定到不同的对象?,wpf,xaml,binding,timer,Wpf,Xaml,Binding,Timer,我想根据带有时间变量的函数(Lissagous)在画布上移动一个小椭圆。有两个滑块可以改变函数的水平和垂直振幅,函数本身应该在定时器滴答声中调用(这实际上就是问题所在)。我成功地管理了滑块值+函数参数的绑定(使用XAML中的ObjectDataProvider标记),还使用canvas.Left和canvas.Top对函数输出+画布上椭圆的坐标进行了绑定。 问题是,据我所知,这种绑定(对于输入和输出)只有在用户更改滑块时才起作用。这意味着,如果我在计时器中调用该函数,它会在每个刻度上生成新的数字

我想根据带有时间变量的函数(Lissagous)在画布上移动一个小椭圆。有两个滑块可以改变函数的水平和垂直振幅,函数本身应该在定时器滴答声中调用(这实际上就是问题所在)。我成功地管理了滑块值+函数参数的绑定(使用XAML中的
ObjectDataProvider
标记),还使用
canvas.Left
canvas.Top
对函数输出+画布上椭圆的坐标进行了绑定。 问题是,据我所知,这种绑定(对于输入和输出)只有在用户更改滑块时才起作用。这意味着,如果我在计时器中调用该函数,它会在每个刻度上生成新的数字,但不会改变椭圆在画布上的位置。但是,如果用户移动滑块,椭圆将相应地在画布上移动,而与t的变化无关。我是不是期望太高了?我是否以某种方式限制了函数的输出?如果是这样,我应该怎么做才能调用函数来移动椭圆,无论滑块是否被更改。 以下是我的XAML代码的大部分:

<Window.Resources>
    <ObjectDataProvider x:Key="lissagousX"
        ObjectType="{x:Type LissagousXAML:Lissagous}" MethodName="LissFuncX">
        <ObjectDataProvider.MethodParameters>
            <system:Double>1</system:Double>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    <ObjectDataProvider x:Key="lissagousY"
        ObjectType="{x:Type LissagousXAML:Lissagous}" MethodName="LissFuncY">
        <ObjectDataProvider.MethodParameters>
            <system:Double>1</system:Double>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>


已编辑:我只需要使用纯绑定而不使用事件处理程序来管理此概念。

如果将UI绑定到视图模型中的属性,会更容易,如下所示。变量名与维基百科文章中使用的变量名相对应

现在,您可以像这样绑定到视图模型属性:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <Canvas Margin="200">
        <Ellipse Fill="Black" Height="10" Width="10"
                 Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}" />
    </Canvas>

    <Slider Grid.Row="1" Orientation="Horizontal" Width="100"
            Minimum="50" Maximum="200" Value="{Binding A}"/>
    <Slider Grid.Column="1" Orientation="Vertical" Height="100"
            Minimum="50" Maximum="200" Value="{Binding B}"/>
</Grid>
public MainWindow()
{
    InitializeComponent();

    var viewModel = new LissajousViewModel
    {
        a = 1,
        b = 1.5,
        A = 100,
        B = 100
    };

    var timer = new DispatcherTimer
    {
        Interval = TimeSpan.FromMilliseconds(20),
        IsEnabled = true
    };

    timer.Tick += (s, e) => viewModel.Update();

    DataContext = viewModel;
}

克莱门斯,你的代码工作得很好。我非常感激。但如果你能告诉我我的错误,告诉我为什么它不起作用,或者告诉我如何改变它,我将不胜感激。这样我会学到更多!我刚刚编辑了我的代码。很抱歉,我没有强调这一点,我需要使用绑定而不是处理程序来完成:(核心思想是数据绑定与属性一起工作(与方法不太好),并且有一个通用的体系结构模式,称为MVVM,它可以帮助您分离应用程序的各个层。
public double LissFuncX(double A)

public double LissFuncY(double B)
public class LissajousViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private DateTime startTime = DateTime.Now;

    public double a { get; set; }
    public double b { get; set; }
    public double A { get; set; }
    public double B { get; set; }
    public double X { get; private set; }
    public double Y { get; private set; }

    public void Update()
    {
        var t = (DateTime.Now - startTime).TotalSeconds;
        X = A * Math.Sin(a * t);
        Y = B * Math.Cos(b * t);
        RaisePropertyChanged("X");
        RaisePropertyChanged("Y");
    }

    private void RaisePropertyChanged(string propertyName)
    {
        var propertyChanged = PropertyChanged;
        if (propertyChanged != null)
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <Canvas Margin="200">
        <Ellipse Fill="Black" Height="10" Width="10"
                 Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}" />
    </Canvas>

    <Slider Grid.Row="1" Orientation="Horizontal" Width="100"
            Minimum="50" Maximum="200" Value="{Binding A}"/>
    <Slider Grid.Column="1" Orientation="Vertical" Height="100"
            Minimum="50" Maximum="200" Value="{Binding B}"/>
</Grid>
public MainWindow()
{
    InitializeComponent();

    var viewModel = new LissajousViewModel
    {
        a = 1,
        b = 1.5,
        A = 100,
        B = 100
    };

    var timer = new DispatcherTimer
    {
        Interval = TimeSpan.FromMilliseconds(20),
        IsEnabled = true
    };

    timer.Tick += (s, e) => viewModel.Update();

    DataContext = viewModel;
}