Why is the Binding of the Point3DCollection not working?

时间:2019-04-23 15:16:30

标签: wpf mvvm data-binding

Hey there,

the generation of my Point3DCollection works fine and i get the Mesh in the Viewport3D (https://imgur.com/5Hzitw2), but the calculateNoise() doesnt update my bound Positions in the Viewport3D even though the OnPropertyChanged Method in my ViewModel get's called. What am I doing wrong here?

Thanks in advance, KonstIT

XAML:

<Viewport3D>
    <Viewport3D.Camera>
        <PerspectiveCamera x:Name="camera"/>
    </Viewport3D.Camera>
    <ModelVisual3D>
        <ModelVisual3D.Content>
            <Model3DGroup>
                <DirectionalLight Color="White" Direction="-1, -1, -3" />
                <GeometryModel3D>
                    <GeometryModel3D.Geometry>
                        <MeshGeometry3D Positions="{Binding Positions}" TriangleIndices="{Binding TriangleIndices}"/>
                    </GeometryModel3D.Geometry>
                    <GeometryModel3D.Material>
                        <DiffuseMaterial Brush="White"/>
                    </GeometryModel3D.Material>
                </GeometryModel3D>
            </Model3DGroup>
        </ModelVisual3D.Content>
    </ModelVisual3D>
</Viewport3D>

ViewportViewModel:

 internal class ViewportViewModel : INotifyPropertyChanged
 {
     private int _terrainSize;
     private Point3DCollection _positions;
     private Int32Collection _triangleIndices;
     private Random random = new Random();

     public Point3DCollection Positions
        {
            get
            {
                return _positions;
            }
            set
            {
                _positions = value;
                OnPropertyChanged("Positions");
            }
        }
     public Int32Collection TriangleIndices
        {
            get
            {
                return _triangleIndices;
            }
            set
            {
                _triangleIndices = value;
                OnPropertyChanged("TriangleIndices");
            }
        }

     public ViewportViewModel()
     {
         _terrainSize = 56;
         _positions = new Point3DCollection();
         _triangleIndices = new Int32Collection();
         GeneratePositions();
         GenerateTriangleIndices();
         CalculateNoiseCommand = new CalculateNoiseCommand(this);
     }

     private void GeneratePositions()
        { //Works }

     private void GenerateTriangleIndices()
        { //Works }

     //Handling
     ...

     internal void CalculateNoise()
     {
         for (int i = 0; i < _terrainSize * _terrainSize; i++)
         {
             Point3D point = new Point3D();
             point = Positions[i];
             point.Y = random.Next(10) / 10.0;
             Positions[i] = point;
         }
         OnPropertyChanged("Positions");
     }

     #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                Console.WriteLine("ViewportViewModel: " + propertyName);
            }
        }

        #endregion

 }

The Code to replace the current Point3DCollection. It's the same as the GeneratePositions() which is called at the constructor, just with the Positions.Clear() method at the beginning. It's called via the CalculateNoise().

        private void ReplacePositions()
        {
            if(Positions.Count > 0)
            {
                Positions.Clear();
            }

            var column = 0;
            var row = 0;
            Point3D point = new Point3D();

            for (int i = 0; i < _terrainSize * _terrainSize; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (j == 0)
                        point.X = ((float)column / ((float)_terrainSize - 1) - 0.5) * 2;
                    if (j == 1)
                        point.Y = 0;
                    if (j == 2)
                        point.Z = ((float)row / ((float)_terrainSize - 1) - 0.5) * 2;
                }

                Positions.Add(point);

                // Calculate next row & column
                column++;
                if (column % _terrainSize == 0)
                {
                    row++;
                }
                column %= _terrainSize;
            }
        }

        internal void CalculateNoise()
        {
            ReplacePositions();
            OnPropertyChanged("Positions");
        }

1 个答案:

答案 0 :(得分:0)

public class GeometryTips : ViewModelBase
{
    #region " Private Fields "
    private int _terrainSize = 56;
    private Random random = new Random();
    #endregion

    #region " Public Properties "

    #region " MeshGeo "
    private MeshGeometry3D _MeshGeo;
    public MeshGeometry3D MeshGeo
    {
        get { return _MeshGeo; }
        set { this.Set(ref _MeshGeo, value); }
    }
    #endregion

    #endregion

    #region " Commands "

    #region " Create3DCommand "
    public RelayCommand Create3DCommand { get; private set; }
    private void Create3D()
    {
        for (int i = 0; i < _terrainSize * _terrainSize; i++)
        {
            Point3D point = new Point3D();
            point = MeshGeo.Positions[i];
            point.Y = random.Next(10) / 10.0;
            MeshGeo.Positions[i] = point;
        }
    }
    #endregion

    #endregion

    #region " Constructor "
    /// <summary>
    /// GeometryTips
    /// </summary>
    public GeometryTips()
    {
        this.Create3DCommand = new RelayCommand(Create3D);
        this._MeshGeo = new MeshGeometry3D();
        GeneratePositions();
        GenerateTriangleIndices();
    }
    #endregion

    #region " Private Functions "

    #region " GeneratePositions "
    /// <summary>
    /// GeneratePositions
    /// </summary>
    private void GeneratePositions()
    {

        var column = 0;
        var row = 0;
        Point3D point = new Point3D();

        for (int i = 0; i < _terrainSize * _terrainSize; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (j == 0)
                    point.X = ((float)column / ((float)_terrainSize - 1) - 0.5) * 2;
                if (j == 1)
                    point.Y = 0;
                if (j == 2)
                    point.Z = ((float)row / ((float)_terrainSize - 1) - 0.5) * 2;
            }
            _MeshGeo.Positions.Add(point);

            // Calculate next row & column
            column++;
            if (column % _terrainSize == 0)
            {
                row++;
            }
            column %= _terrainSize;
        }
    }
    #endregion

    #region " GenerateTriangleIndices "
    /// <summary>
    /// GenerateTriangleIndices
    /// </summary>
    private void GenerateTriangleIndices()
    {
        var value = 0;

        for (int i = 0; i < _terrainSize * _terrainSize - _terrainSize; i++)
        {
            for (int triangle = 0; triangle < 3; triangle++)
            {
                if (i % _terrainSize == 0)
                {
                    break;
                }
                if (triangle == 0)
                {
                    value = i;
                }
                else if (triangle == 1)
                {
                    value = i + triangle + _terrainSize - 2;
                }
                else if (triangle == 2)
                {
                    value = i + triangle + _terrainSize - 2;
                }
                _MeshGeo.TriangleIndices.Add(value);
            }
            for (int triangle = 0; triangle < 3; triangle++)
            {
                if (i > 0 && ((i + 1) % _terrainSize) == 0)
                {
                    break;
                }
                if (triangle == 0)
                {
                    value = i + triangle;
                }
                else if (triangle == 1)
                {
                    value = i + triangle + _terrainSize - 1;
                }
                else if (triangle == 2)
                {
                    value = i + triangle - 1;
                }
                _MeshGeo.TriangleIndices.Add(value);
            }
        }
    }
    #endregion

    #endregion
}

我使用MVVM Light创建了这个视图模型。

我使用MeshGeometry3D类进行绑定。

这是我的xaml:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="10"></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition Width="10"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="10"></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="10"></RowDefinition>
    </Grid.RowDefinitions>
    <Viewport3D Grid.Column="1" Grid.Row="1">
        <Viewport3D.Camera>
            <PerspectiveCamera x:Name="camera"/>
        </Viewport3D.Camera>
        <ModelVisual3D>
            <ModelVisual3D.Content>
                <Model3DGroup>
                    <DirectionalLight Direction="-1, -1, -3"/>
                    <GeometryModel3D Geometry="{Binding MeshGeo}">
                        <GeometryModel3D.Material>
                            <DiffuseMaterial Brush="White"/>
                        </GeometryModel3D.Material>
                    </GeometryModel3D>
                </Model3DGroup>
            </ModelVisual3D.Content>
        </ModelVisual3D>
    </Viewport3D>
    <Button Grid.Column="1" Grid.Row="2" Content="Handle" Command="{Binding Create3DCommand}"></Button>
</Grid>

这对我有用,希望对您有帮助...